You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

587 lines
17 KiB

  1. /*
  2. * This file is part of GNUnet
  3. * Copyright (C) 2013 GNUnet e.V.
  4. *
  5. * GNUnet is free software: you can redistribute it and/or modify it
  6. * under the terms of the GNU Affero General Public License as published
  7. * by the Free Software Foundation, either version 3 of the License,
  8. * or (at your option) any later version.
  9. *
  10. * GNUnet is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. SPDX-License-Identifier: AGPL3.0-or-later
  18. */
  19. /**
  20. * @file psycstore/test_psycstore.c
  21. * @brief Test for the PSYCstore service.
  22. * @author Gabor X Toth
  23. * @author Christian Grothoff
  24. */
  25. #include <inttypes.h>
  26. #include "platform.h"
  27. #include "gnunet_util_lib.h"
  28. #include "gnunet_common.h"
  29. #include "gnunet_testing_lib.h"
  30. #include "gnunet_psycstore_service.h"
  31. #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
  32. /**
  33. * Return value from 'main'.
  34. */
  35. static int res;
  36. /**
  37. * Handle to PSYCstore service.
  38. */
  39. static struct GNUNET_PSYCSTORE_Handle *h;
  40. /**
  41. * Handle to PSYCstore operation.
  42. */
  43. static struct GNUNET_PSYCSTORE_OperationHandle *op;
  44. /**
  45. * Handle for task for timeout termination.
  46. */
  47. static struct GNUNET_SCHEDULER_Task *end_badly_task;
  48. static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
  49. static struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key;
  50. static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
  51. static struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;
  52. static struct FragmentClosure
  53. {
  54. uint8_t n;
  55. uint8_t n_expected;
  56. uint64_t flags[16];
  57. struct GNUNET_MULTICAST_MessageHeader *msg[16];
  58. } fcls;
  59. struct StateClosure {
  60. size_t n;
  61. char *name[16];
  62. void *value[16];
  63. size_t value_size[16];
  64. } scls;
  65. static struct GNUNET_PSYC_Modifier modifiers[16];
  66. /**
  67. * Clean up all resources used.
  68. */
  69. static void
  70. cleanup ()
  71. {
  72. if (NULL != op)
  73. {
  74. GNUNET_PSYCSTORE_operation_cancel (op);
  75. op = NULL;
  76. }
  77. if (NULL != h)
  78. {
  79. GNUNET_PSYCSTORE_disconnect (h);
  80. h = NULL;
  81. }
  82. if (NULL != channel_key)
  83. {
  84. GNUNET_free (channel_key);
  85. channel_key = NULL;
  86. }
  87. if (NULL != slave_key)
  88. {
  89. GNUNET_free (slave_key);
  90. slave_key = NULL;
  91. }
  92. GNUNET_SCHEDULER_shutdown ();
  93. }
  94. /**
  95. * Terminate the testcase (failure).
  96. *
  97. * @param cls NULL
  98. */
  99. static void
  100. end_badly (void *cls)
  101. {
  102. res = 1;
  103. cleanup ();
  104. }
  105. /**
  106. * Terminate the testcase (success).
  107. *
  108. * @param cls NULL
  109. */
  110. static void
  111. end_normally (void *cls)
  112. {
  113. res = 0;
  114. cleanup ();
  115. }
  116. /**
  117. * Finish the testcase (successfully).
  118. */
  119. static void
  120. end ()
  121. {
  122. if (NULL != end_badly_task)
  123. {
  124. GNUNET_SCHEDULER_cancel (end_badly_task);
  125. end_badly_task = NULL;
  126. }
  127. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
  128. &end_normally, NULL);
  129. }
  130. static void
  131. state_reset_result (void *cls,
  132. int64_t result,
  133. const char *err_msg,
  134. uint16_t err_msg_size)
  135. {
  136. op = NULL;
  137. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  138. "state_reset_result:\t%d\n",
  139. (int) result);
  140. GNUNET_assert (GNUNET_OK == result);
  141. op = GNUNET_PSYCSTORE_state_reset (h, &channel_pub_key,
  142. &state_reset_result, cls);
  143. GNUNET_PSYCSTORE_operation_cancel (op);
  144. op = NULL;
  145. end ();
  146. }
  147. static int
  148. state_result (void *cls,
  149. const char *name,
  150. const void *value,
  151. uint32_t value_size)
  152. {
  153. struct StateClosure *scls = cls;
  154. const char *nam = scls->name[scls->n];
  155. const void *val = scls->value[scls->n];
  156. size_t val_size = scls->value_size[scls->n++];
  157. if (value_size == val_size
  158. && 0 == memcmp (value, val, val_size)
  159. && 0 == strcmp (name, nam))
  160. {
  161. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  162. " variable %s matches\n",
  163. name);
  164. return GNUNET_YES;
  165. }
  166. else
  167. {
  168. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  169. " variable %s differs\nReceived: %.*s\nExpected: %.*s\n",
  170. name, (int) value_size, (char*) value, (int) val_size, (char*) val);
  171. GNUNET_assert (0);
  172. return GNUNET_SYSERR;
  173. }
  174. }
  175. static void
  176. state_get_prefix_result (void *cls, int64_t result,
  177. const char *err_msg, uint16_t err_msg_size)
  178. {
  179. struct StateClosure *scls = cls;
  180. op = NULL;
  181. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_prefix_result:\t%ld\n", (long int) result);
  182. GNUNET_assert (GNUNET_OK == result && 2 == scls->n);
  183. op = GNUNET_PSYCSTORE_state_reset (h, &channel_pub_key,
  184. &state_reset_result, cls);
  185. }
  186. static void
  187. state_get_result (void *cls, int64_t result,
  188. const char *err_msg, uint16_t err_msg_size)
  189. {
  190. op = NULL;
  191. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_result:\t%ld\n", (long int) result);
  192. GNUNET_assert (GNUNET_OK == result);
  193. scls.n = 0;
  194. scls.name[0] = "_sync_bar";
  195. scls.value[0] = "ten eleven twelve";
  196. scls.value_size[0] = sizeof ("ten eleven twelve") - 1;
  197. scls.name[1] = "_sync_foo";
  198. scls.value[1] = "three two one";
  199. scls.value_size[1] = sizeof ("three two one") - 1;
  200. op = GNUNET_PSYCSTORE_state_get_prefix (h, &channel_pub_key, "_sync",
  201. &state_result,
  202. &state_get_prefix_result, &scls);
  203. }
  204. static void
  205. counters_result (void *cls, int status, uint64_t max_fragment_id,
  206. uint64_t max_message_id, uint64_t max_group_generation,
  207. uint64_t max_state_message_id)
  208. {
  209. struct FragmentClosure *fcls = cls;
  210. int result = 0;
  211. op = NULL;
  212. if (GNUNET_OK == status
  213. && max_fragment_id == GNUNET_ntohll (fcls->msg[2]->fragment_id)
  214. && max_message_id == GNUNET_ntohll (fcls->msg[2]->message_id)
  215. && max_group_generation == GNUNET_ntohll (fcls->msg[2]->group_generation)
  216. && max_state_message_id == GNUNET_ntohll (fcls->msg[0]->message_id))
  217. result = 1;
  218. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "counters_get:\t%d\n", result);
  219. GNUNET_assert (result == 1);
  220. scls.n = 0;
  221. scls.name[0] = "_sync_bar";
  222. scls.value[0] = "ten eleven twelve";
  223. scls.value_size[0] = sizeof ("ten eleven twelve") - 1;
  224. op = GNUNET_PSYCSTORE_state_get (h, &channel_pub_key, "_sync_bar_x_yy_zzz",
  225. &state_result, &state_get_result, &scls);
  226. }
  227. static void
  228. state_modify_result (void *cls, int64_t result,
  229. const char *err_msg, uint16_t err_msg_size)
  230. {
  231. op = NULL;
  232. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_modify_result:\t%ld\n", (long int) result);
  233. GNUNET_assert (GNUNET_OK == result);
  234. op = GNUNET_PSYCSTORE_counters_get (h, &channel_pub_key,
  235. &counters_result, cls);
  236. }
  237. static void
  238. state_sync_result (void *cls, int64_t result,
  239. const char *err_msg, uint16_t err_msg_size)
  240. {
  241. struct FragmentClosure *fcls = cls;
  242. op = NULL;
  243. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_sync_result:\t%ld\n", (long int) result);
  244. GNUNET_assert (GNUNET_OK == result);
  245. op = GNUNET_PSYCSTORE_state_modify (h, &channel_pub_key,
  246. GNUNET_ntohll (fcls->msg[0]->message_id),
  247. 0, state_modify_result, fcls);
  248. }
  249. static int
  250. fragment_result (void *cls,
  251. struct GNUNET_MULTICAST_MessageHeader *msg,
  252. enum GNUNET_PSYCSTORE_MessageFlags flags)
  253. {
  254. struct FragmentClosure *fcls = cls;
  255. GNUNET_assert (fcls->n < fcls->n_expected);
  256. struct GNUNET_MULTICAST_MessageHeader *msg0 = fcls->msg[fcls->n];
  257. uint64_t flags0 = fcls->flags[fcls->n++];
  258. if (flags == flags0 && msg->header.size == msg0->header.size
  259. && 0 == memcmp (msg, msg0, ntohs (msg->header.size)))
  260. {
  261. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " fragment %" PRIu64 " matches\n",
  262. GNUNET_ntohll (msg->fragment_id));
  263. return GNUNET_YES;
  264. }
  265. else
  266. {
  267. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  268. " fragment differs: expected %" PRIu64 ", got %" PRIu64 "\n",
  269. GNUNET_ntohll (msg0->fragment_id),
  270. GNUNET_ntohll (msg->fragment_id));
  271. GNUNET_assert (0);
  272. return GNUNET_SYSERR;
  273. }
  274. }
  275. static void
  276. message_get_latest_result (void *cls, int64_t result,
  277. const char *err_msg, uint16_t err_msg_size)
  278. {
  279. struct FragmentClosure *fcls = cls;
  280. op = NULL;
  281. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_latest:\t%ld\n", (long int) result);
  282. GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
  283. modifiers[0] = (struct GNUNET_PSYC_Modifier) {
  284. .oper = '=',
  285. .name = "_sync_foo",
  286. .value = "three two one",
  287. .value_size = sizeof ("three two one") - 1
  288. };
  289. modifiers[1] = (struct GNUNET_PSYC_Modifier) {
  290. .oper = '=',
  291. .name = "_sync_bar",
  292. .value = "ten eleven twelve",
  293. .value_size = sizeof ("ten eleven twelve") - 1
  294. };
  295. op = GNUNET_PSYCSTORE_state_sync (h, &channel_pub_key,
  296. GNUNET_ntohll (fcls->msg[0]->message_id) + 1,
  297. GNUNET_ntohll (fcls->msg[0]->message_id) + 2,
  298. 2, modifiers, state_sync_result, fcls);
  299. }
  300. static void
  301. message_get_result (void *cls, int64_t result,
  302. const char *err_msg, uint16_t err_msg_size)
  303. {
  304. struct FragmentClosure *fcls = cls;
  305. op = NULL;
  306. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get:\t%ld\n", (long int) result);
  307. GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
  308. fcls->n = 0;
  309. fcls->n_expected = 3;
  310. op = GNUNET_PSYCSTORE_message_get_latest (h, &channel_pub_key, &slave_pub_key,
  311. 1, "", &fragment_result,
  312. &message_get_latest_result, fcls);
  313. }
  314. static void
  315. message_get_fragment_result (void *cls, int64_t result,
  316. const char *err_msg, uint16_t err_msg_size)
  317. {
  318. struct FragmentClosure *fcls = cls;
  319. op = NULL;
  320. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_fragment:\t%ld\n", (long int) result);
  321. GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
  322. fcls->n = 0;
  323. fcls->n_expected = 3;
  324. uint64_t message_id = GNUNET_ntohll (fcls->msg[0]->message_id);
  325. op = GNUNET_PSYCSTORE_message_get (h, &channel_pub_key, &slave_pub_key,
  326. message_id, message_id, 0, "",
  327. &fragment_result,
  328. &message_get_result, fcls);
  329. }
  330. static void
  331. fragment_get_latest_result (void *cls, int64_t result,
  332. const char *err_msg, uint16_t err_msg_size)
  333. {
  334. struct FragmentClosure *fcls = cls;
  335. op = NULL;
  336. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_get_latest:\t%ld\n", (long int) result);
  337. GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
  338. fcls->n = 1;
  339. fcls->n_expected = 2;
  340. op = GNUNET_PSYCSTORE_message_get_fragment (h, &channel_pub_key, &slave_pub_key,
  341. GNUNET_ntohll (fcls->msg[1]->message_id),
  342. GNUNET_ntohll (fcls->msg[1]->fragment_offset),
  343. &fragment_result,
  344. &message_get_fragment_result, fcls);
  345. }
  346. static void
  347. fragment_get_result (void *cls, int64_t result,
  348. const char *err_msg, uint16_t err_msg_size)
  349. {
  350. struct FragmentClosure *fcls = cls;
  351. op = NULL;
  352. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  353. "fragment_get:\t%d\n",
  354. (int) result);
  355. GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
  356. fcls->n = 0;
  357. fcls->n_expected = 3;
  358. op = GNUNET_PSYCSTORE_fragment_get_latest (h, &channel_pub_key,
  359. &slave_pub_key, fcls->n_expected,
  360. &fragment_result,
  361. &fragment_get_latest_result, fcls);
  362. }
  363. static void
  364. fragment_store_result (void *cls, int64_t result,
  365. const char *err_msg, uint16_t err_msg_size)
  366. {
  367. op = NULL;
  368. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_store:\t%ld\n", (long int) result);
  369. GNUNET_assert (GNUNET_OK == result);
  370. if ((intptr_t) cls == GNUNET_YES)
  371. { /* last fragment */
  372. fcls.n = 0;
  373. fcls.n_expected = 1;
  374. uint64_t fragment_id = GNUNET_ntohll (fcls.msg[0]->fragment_id);
  375. op = GNUNET_PSYCSTORE_fragment_get (h, &channel_pub_key, &slave_pub_key,
  376. fragment_id, fragment_id,
  377. &fragment_result,
  378. &fragment_get_result, &fcls);
  379. }
  380. }
  381. static void
  382. fragment_store ()
  383. {
  384. struct GNUNET_MULTICAST_MessageHeader *msg;
  385. fcls.flags[0] = GNUNET_PSYCSTORE_MESSAGE_STATE;
  386. fcls.msg[0] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
  387. GNUNET_assert (msg != NULL);
  388. msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
  389. msg->header.size = htons (sizeof (*msg) + sizeof (channel_pub_key));
  390. msg->hop_counter = htonl (9);
  391. msg->fragment_id = GNUNET_htonll (INT64_MAX - 8);
  392. msg->fragment_offset = GNUNET_htonll (0);
  393. msg->message_id = GNUNET_htonll (INT64_MAX - 10);
  394. msg->group_generation = GNUNET_htonll (INT64_MAX - 3);
  395. msg->flags = htonl (GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT);
  396. GNUNET_memcpy (&msg[1], &channel_pub_key, sizeof (channel_pub_key));
  397. msg->purpose.size = htonl (ntohs (msg->header.size)
  398. - sizeof (msg->header)
  399. - sizeof (msg->hop_counter)
  400. - sizeof (msg->signature));
  401. msg->purpose.purpose = htonl (234);
  402. GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (channel_key, &msg->purpose,
  403. &msg->signature));
  404. op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[0],
  405. &fragment_store_result, GNUNET_NO);
  406. fcls.flags[1] = GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED;
  407. fcls.msg[1] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
  408. GNUNET_memcpy (msg, fcls.msg[0], sizeof (*msg) + sizeof (channel_pub_key));
  409. msg->fragment_id = GNUNET_htonll (INT64_MAX - 4);
  410. msg->fragment_offset = GNUNET_htonll (1024);
  411. op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[1],
  412. &fragment_store_result, GNUNET_NO);
  413. fcls.flags[2] = GNUNET_PSYCSTORE_MESSAGE_STATE_HASH;
  414. fcls.msg[2] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
  415. GNUNET_memcpy (msg, fcls.msg[1], sizeof (*msg) + sizeof (channel_pub_key));
  416. msg->fragment_id = GNUNET_htonll (INT64_MAX);
  417. msg->fragment_offset = GNUNET_htonll (16384);
  418. op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[2],
  419. &fragment_store_result, (void *) GNUNET_YES);
  420. }
  421. static void
  422. membership_test_result (void *cls, int64_t result,
  423. const char *err_msg, uint16_t err_msg_size)
  424. {
  425. op = NULL;
  426. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_test:\t%ld\n", (long int) result);
  427. GNUNET_assert (GNUNET_OK == result);
  428. fragment_store ();
  429. }
  430. static void
  431. membership_store_result (void *cls, int64_t result,
  432. const char *err_msg, uint16_t err_msg_size)
  433. {
  434. op = NULL;
  435. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_store:\t%ld\n", (long int) result);
  436. GNUNET_assert (GNUNET_OK == result);
  437. op = GNUNET_PSYCSTORE_membership_test (h, &channel_pub_key, &slave_pub_key,
  438. INT64_MAX - 10, 2,
  439. &membership_test_result, NULL);
  440. }
  441. /**
  442. * Main function of the test, run from scheduler.
  443. *
  444. * @param cls NULL
  445. * @param cfg configuration we use (also to connect to PSYCstore service)
  446. * @param peer handle to access more of the peer (not used)
  447. */
  448. static void
  449. #if DEBUG_TEST_PSYCSTORE
  450. run (void *cls, char *const *args, const char *cfgfile,
  451. const struct GNUNET_CONFIGURATION_Handle *cfg)
  452. #else
  453. run (void *cls,
  454. const struct GNUNET_CONFIGURATION_Handle *cfg,
  455. struct GNUNET_TESTING_Peer *peer)
  456. #endif
  457. {
  458. end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
  459. h = GNUNET_PSYCSTORE_connect (cfg);
  460. GNUNET_assert (NULL != h);
  461. channel_key = GNUNET_CRYPTO_eddsa_key_create ();
  462. slave_key = GNUNET_CRYPTO_ecdsa_key_create ();
  463. GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
  464. GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);
  465. op = GNUNET_PSYCSTORE_membership_store (h, &channel_pub_key, &slave_pub_key,
  466. GNUNET_YES, INT64_MAX - 5,
  467. INT64_MAX - 10, 2,
  468. &membership_store_result, NULL);
  469. }
  470. int
  471. main (int argc, char *argv[])
  472. {
  473. res = 1;
  474. #if DEBUG_TEST_PSYCSTORE
  475. const struct GNUNET_GETOPT_CommandLineOption opts[] = {
  476. GNUNET_GETOPT_OPTION_END
  477. };
  478. if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-psycstore",
  479. "test-psycstore [options]",
  480. opts, &run, NULL))
  481. return 1;
  482. #else
  483. if (0 != GNUNET_TESTING_service_run ("test-psycstore", "psycstore",
  484. "test_psycstore.conf", &run, NULL))
  485. return 1;
  486. #endif
  487. return res;
  488. }
  489. /* end of test_psycstore.c */