test_set_union_result_symmetric.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012, 2016 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file set/test_set_union_result_smmetric
  18. * @brief testcase for symmetric result mode of the union set operation
  19. * @author Florian Dold
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "gnunet_testing_lib.h"
  25. #include "gnunet_set_service.h"
  26. /**
  27. * Value to return from #main().
  28. */
  29. static int ret;
  30. static struct GNUNET_PeerIdentity local_id;
  31. static struct GNUNET_HashCode app_id;
  32. static struct GNUNET_SET_Handle *set1;
  33. static struct GNUNET_SET_Handle *set2;
  34. static struct GNUNET_SET_ListenHandle *listen_handle;
  35. static const struct GNUNET_CONFIGURATION_Handle *config;
  36. static struct GNUNET_SET_OperationHandle *oh1;
  37. static struct GNUNET_SET_OperationHandle *oh2;
  38. static int iter_count;
  39. /**
  40. * Are we testing correctness for the empty set union?
  41. */
  42. static int empty;
  43. /**
  44. * Number of elements found in set 1
  45. */
  46. static unsigned int count_set1;
  47. /**
  48. * Number of elements found in set 2
  49. */
  50. static unsigned int count_set2;
  51. /**
  52. * Task that is run when the test times out.
  53. */
  54. static struct GNUNET_SCHEDULER_Task *timeout_task;
  55. static void
  56. result_cb_set1 (void *cls,
  57. const struct GNUNET_SET_Element *element,
  58. uint64_t current_size,
  59. enum GNUNET_SET_Status status)
  60. {
  61. switch (status)
  62. {
  63. case GNUNET_SET_STATUS_ADD_LOCAL:
  64. count_set1++;
  65. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  66. "set 1: got element\n");
  67. break;
  68. case GNUNET_SET_STATUS_FAILURE:
  69. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  70. "set 1: failure\n");
  71. oh1 = NULL;
  72. ret = 1;
  73. if (NULL != timeout_task)
  74. {
  75. GNUNET_SCHEDULER_cancel (timeout_task);
  76. timeout_task = NULL;
  77. }
  78. GNUNET_SCHEDULER_shutdown ();
  79. break;
  80. case GNUNET_SET_STATUS_DONE:
  81. oh1 = NULL;
  82. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  83. "set 1: done\n");
  84. GNUNET_SET_destroy (set1);
  85. set1 = NULL;
  86. if (NULL == set2)
  87. {
  88. if (NULL != timeout_task)
  89. {
  90. GNUNET_SCHEDULER_cancel (timeout_task);
  91. timeout_task = NULL;
  92. }
  93. GNUNET_SCHEDULER_shutdown ();
  94. }
  95. break;
  96. case GNUNET_SET_STATUS_ADD_REMOTE:
  97. break;
  98. default:
  99. GNUNET_assert (0);
  100. }
  101. }
  102. static void
  103. result_cb_set2 (void *cls,
  104. const struct GNUNET_SET_Element *element,
  105. uint64_t current_size,
  106. enum GNUNET_SET_Status status)
  107. {
  108. switch (status)
  109. {
  110. case GNUNET_SET_STATUS_ADD_LOCAL:
  111. count_set2++;
  112. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  113. "set 2: got element\n");
  114. break;
  115. case GNUNET_SET_STATUS_FAILURE:
  116. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  117. "set 2: failure\n");
  118. oh2 = NULL;
  119. ret = 1;
  120. if (NULL != timeout_task)
  121. {
  122. GNUNET_SCHEDULER_cancel (timeout_task);
  123. timeout_task = NULL;
  124. }
  125. GNUNET_SCHEDULER_shutdown ();
  126. break;
  127. case GNUNET_SET_STATUS_DONE:
  128. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  129. "set 2: done\n");
  130. oh2 = NULL;
  131. GNUNET_SET_destroy (set2);
  132. set2 = NULL;
  133. if (NULL == set1)
  134. {
  135. if (NULL != timeout_task)
  136. {
  137. GNUNET_SCHEDULER_cancel (timeout_task);
  138. timeout_task = NULL;
  139. }
  140. GNUNET_SCHEDULER_shutdown ();
  141. }
  142. break;
  143. case GNUNET_SET_STATUS_ADD_REMOTE:
  144. break;
  145. default:
  146. GNUNET_assert (0);
  147. }
  148. }
  149. static void
  150. listen_cb (void *cls,
  151. const struct GNUNET_PeerIdentity *other_peer,
  152. const struct GNUNET_MessageHeader *context_msg,
  153. struct GNUNET_SET_Request *request)
  154. {
  155. GNUNET_assert (NULL != context_msg);
  156. GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_DUMMY);
  157. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  158. "listen cb called\n");
  159. oh2 = GNUNET_SET_accept (request,
  160. GNUNET_SET_RESULT_SYMMETRIC,
  161. (struct GNUNET_SET_Option[]) { 0 },
  162. &result_cb_set2,
  163. NULL);
  164. GNUNET_SET_commit (oh2,
  165. set2);
  166. }
  167. /**
  168. * Start the set operation.
  169. *
  170. * @param cls closure, unused
  171. */
  172. static void
  173. start (void *cls)
  174. {
  175. struct GNUNET_MessageHeader context_msg;
  176. context_msg.size = htons (sizeof context_msg);
  177. context_msg.type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
  178. listen_handle = GNUNET_SET_listen (config,
  179. GNUNET_SET_OPERATION_UNION,
  180. &app_id,
  181. &listen_cb, NULL);
  182. oh1 = GNUNET_SET_prepare (&local_id,
  183. &app_id,
  184. &context_msg,
  185. GNUNET_SET_RESULT_SYMMETRIC,
  186. (struct GNUNET_SET_Option[]) { 0 },
  187. &result_cb_set1, NULL);
  188. GNUNET_SET_commit (oh1, set1);
  189. }
  190. /**
  191. * Initialize the second set, continue
  192. *
  193. * @param cls closure, unused
  194. */
  195. static void
  196. init_set2 (void *cls)
  197. {
  198. struct GNUNET_SET_Element element;
  199. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  200. "initializing set 2\n");
  201. if (empty)
  202. {
  203. start (NULL);
  204. return;
  205. }
  206. element.element_type = 0;
  207. element.data = "hello";
  208. element.size = strlen(element.data);
  209. GNUNET_SET_add_element (set2,
  210. &element,
  211. NULL,
  212. NULL);
  213. element.data = "quux";
  214. element.size = strlen(element.data);
  215. GNUNET_SET_add_element (set2,
  216. &element,
  217. NULL,
  218. NULL);
  219. element.data = "baz";
  220. element.size = strlen(element.data);
  221. GNUNET_SET_add_element (set2,
  222. &element,
  223. &start, NULL);
  224. }
  225. /**
  226. * Initialize the first set, continue.
  227. */
  228. static void
  229. init_set1 (void)
  230. {
  231. struct GNUNET_SET_Element element;
  232. if (empty)
  233. {
  234. init_set2 (NULL);
  235. return;
  236. }
  237. element.element_type = 0;
  238. element.data = "hello";
  239. element.size = strlen(element.data);
  240. GNUNET_SET_add_element (set1,
  241. &element,
  242. NULL,
  243. NULL);
  244. element.data = "bar";
  245. element.size = strlen(element.data);
  246. GNUNET_SET_add_element (set1,
  247. &element,
  248. &init_set2,
  249. NULL);
  250. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  251. "initialized set 1\n");
  252. }
  253. static int
  254. iter_cb (void *cls,
  255. const struct GNUNET_SET_Element *element)
  256. {
  257. if (NULL == element)
  258. {
  259. GNUNET_assert (iter_count == 3);
  260. GNUNET_SET_destroy (cls);
  261. return GNUNET_YES;
  262. }
  263. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  264. "iter: got element\n");
  265. iter_count++;
  266. return GNUNET_YES;
  267. }
  268. static void
  269. test_iter ()
  270. {
  271. struct GNUNET_SET_Element element;
  272. struct GNUNET_SET_Handle *iter_set;
  273. iter_count = 0;
  274. iter_set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION);
  275. element.element_type = 0;
  276. element.data = "hello";
  277. element.size = strlen(element.data);
  278. GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
  279. element.data = "bar";
  280. element.size = strlen(element.data);
  281. GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
  282. element.data = "quux";
  283. element.size = strlen(element.data);
  284. GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
  285. GNUNET_SET_iterate (iter_set,
  286. &iter_cb,
  287. iter_set);
  288. }
  289. /**
  290. * Signature of the main function of a task.
  291. *
  292. * @param cls closure
  293. */
  294. static void
  295. timeout_fail (void *cls)
  296. {
  297. timeout_task = NULL;
  298. GNUNET_SCHEDULER_shutdown ();
  299. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  300. "test timed out\n");
  301. ret = 1;
  302. }
  303. /**
  304. * Function run on shutdown.
  305. *
  306. * @param cls closure
  307. */
  308. static void
  309. do_shutdown (void *cls)
  310. {
  311. if (NULL != timeout_task)
  312. {
  313. GNUNET_SCHEDULER_cancel (timeout_task);
  314. timeout_task = NULL;
  315. }
  316. if (NULL != oh1)
  317. {
  318. GNUNET_SET_operation_cancel (oh1);
  319. oh1 = NULL;
  320. }
  321. if (NULL != oh2)
  322. {
  323. GNUNET_SET_operation_cancel (oh2);
  324. oh2 = NULL;
  325. }
  326. if (NULL != set1)
  327. {
  328. GNUNET_SET_destroy (set1);
  329. set1 = NULL;
  330. }
  331. if (NULL != set2)
  332. {
  333. GNUNET_SET_destroy (set2);
  334. set2 = NULL;
  335. }
  336. if (NULL != listen_handle)
  337. {
  338. GNUNET_SET_listen_cancel (listen_handle);
  339. listen_handle = NULL;
  340. }
  341. }
  342. /**
  343. * Signature of the 'main' function for a (single-peer) testcase that
  344. * is run using 'GNUNET_TESTING_peer_run'.
  345. *
  346. * @param cls closure
  347. * @param cfg configuration of the peer that was started
  348. * @param peer identity of the peer that was created
  349. */
  350. static void
  351. run (void *cls,
  352. const struct GNUNET_CONFIGURATION_Handle *cfg,
  353. struct GNUNET_TESTING_Peer *peer)
  354. {
  355. timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
  356. &timeout_fail,
  357. NULL);
  358. GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
  359. NULL);
  360. config = cfg;
  361. GNUNET_TESTING_peer_get_identity (peer,
  362. &local_id);
  363. if (0)
  364. test_iter ();
  365. set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
  366. set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
  367. GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id);
  368. /* test the real set reconciliation */
  369. init_set1 ();
  370. }
  371. int
  372. main (int argc, char **argv)
  373. {
  374. empty = 1;
  375. if (0 != GNUNET_TESTING_peer_run ("test_set_api",
  376. "test_set.conf",
  377. &run, NULL))
  378. {
  379. return 1;
  380. }
  381. GNUNET_assert (0 == count_set1);
  382. GNUNET_assert (0 == count_set2);
  383. empty = 0;
  384. if (0 != GNUNET_TESTING_peer_run ("test_set_api",
  385. "test_set.conf",
  386. &run, NULL))
  387. {
  388. return 1;
  389. }
  390. GNUNET_break (2 == count_set1);
  391. GNUNET_break (1 == count_set2);
  392. return ret;
  393. }