2 * This file is part of GNUnet
3 * (C) 2013 Christian Grothoff (and other contributing authors)
5 * GNUnet is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 3, or (at your
8 * option) any later version.
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 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNUnet; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * @file psycstore/test_psycstore.c
23 * @brief Test for the PSYCstore service.
24 * @author Gabor X Toth
25 * @author Christian Grothoff
29 #include "gnunet_util_lib.h"
30 #include "gnunet_common.h"
31 #include "gnunet_testing_lib.h"
32 #include "gnunet_psycstore_service.h"
34 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
38 * Return value from 'main'.
43 * Handle to PSYCstore service.
45 static struct GNUNET_PSYCSTORE_Handle *h;
48 * Handle to PSYCstore operation.
50 static struct GNUNET_PSYCSTORE_OperationHandle *op;
53 * Handle for task for timeout termination.
55 static GNUNET_SCHEDULER_TaskIdentifier end_badly_task;
57 static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
58 static struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key;
60 static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
61 static struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;
63 static struct FragmentClosure
68 struct GNUNET_MULTICAST_MessageHeader *msg[16];
75 size_t value_size[16];
78 static struct GNUNET_ENV_Modifier modifiers[16];
81 * Clean up all resources used.
88 GNUNET_PSYCSTORE_operation_cancel (op);
93 GNUNET_PSYCSTORE_disconnect (h);
96 if (NULL != channel_key)
98 GNUNET_free (channel_key);
101 if (NULL != slave_key)
103 GNUNET_free (slave_key);
106 GNUNET_SCHEDULER_shutdown ();
111 * Terminate the testcase (failure).
114 * @param tc scheduler context
117 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
125 * Terminate the testcase (success).
128 * @param tc scheduler context
131 end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
139 * Finish the testcase (successfully).
144 if (end_badly_task != GNUNET_SCHEDULER_NO_TASK)
146 GNUNET_SCHEDULER_cancel (end_badly_task);
147 end_badly_task = GNUNET_SCHEDULER_NO_TASK;
149 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
150 &end_normally, NULL);
155 state_reset_result (void *cls, int64_t result, const char *err_msg)
158 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_reset_result:\t%d\n", result);
159 GNUNET_assert (GNUNET_OK == result);
161 op = GNUNET_PSYCSTORE_state_reset (h, &channel_pub_key,
162 &state_reset_result, cls);
163 GNUNET_PSYCSTORE_operation_cancel (op);
170 state_result (void *cls, const char *name, const void *value, size_t value_size)
172 struct StateClosure *scls = cls;
173 const char *nam = scls->name[scls->n];
174 const void *val = scls->value[scls->n];
175 size_t val_size = scls->value_size[scls->n++];
177 if (value_size == val_size
178 && 0 == memcmp (value, val, val_size)
179 && 0 == strcmp (name, nam))
181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " variable %s matches\n", name);
186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
187 " variable %s differs\nReceived: %.*s\nExpected: %.*s\n",
188 name, value_size, value, val_size, val);
190 return GNUNET_SYSERR;
196 state_get_prefix_result (void *cls, int64_t result, const char *err_msg)
198 struct StateClosure *scls = cls;
200 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_prefix_result:\t%d\n", result);
201 GNUNET_assert (GNUNET_OK == result && 2 == scls->n);
203 op = GNUNET_PSYCSTORE_state_reset (h, &channel_pub_key,
204 &state_reset_result, cls);
209 state_get_result (void *cls, int64_t result, const char *err_msg)
212 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_result:\t%d\n", result);
213 GNUNET_assert (GNUNET_OK == result);
217 scls.name[0] = "_sync_bar";
218 scls.value[0] = "ten eleven twelve";
219 scls.value_size[0] = sizeof ("ten eleven twelve") - 1;
221 scls.name[1] = "_sync_foo";
222 scls.value[1] = "one two three";
223 scls.value_size[1] = sizeof ("one two three") - 1;
225 op = GNUNET_PSYCSTORE_state_get_prefix (h, &channel_pub_key, "_sync",
227 &state_get_prefix_result, &scls);
232 counters_result (void *cls, int status, uint64_t max_fragment_id,
233 uint64_t max_message_id, uint64_t max_group_generation,
234 uint64_t max_state_message_id)
236 struct FragmentClosure *fcls = cls;
240 if (GNUNET_OK == status
241 && max_fragment_id == GNUNET_ntohll (fcls->msg[2]->fragment_id)
242 && max_message_id == GNUNET_ntohll (fcls->msg[2]->message_id)
243 && max_group_generation == GNUNET_ntohll (fcls->msg[2]->group_generation)
244 && max_state_message_id == GNUNET_ntohll (fcls->msg[0]->message_id))
247 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "counters_get:\t%d\n", result);
248 GNUNET_assert (result == 1);
251 scls.name[0] = "_bar";
252 scls.value[0] = "four five six";
253 scls.value_size[0] = sizeof ("four five six") - 1;
255 op = GNUNET_PSYCSTORE_state_get (h, &channel_pub_key, "_bar_x_yy_zzz",
256 &state_result, &state_get_result, &scls);
261 state_modify_result (void *cls, int64_t result, const char *err_msg)
264 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_modify_result:\t%d\n", result);
265 GNUNET_assert (GNUNET_OK == result);
267 op = GNUNET_PSYCSTORE_counters_get (h, &channel_pub_key,
268 &counters_result, cls);
273 state_sync_result (void *cls, int64_t result, const char *err_msg)
275 struct FragmentClosure *fcls = cls;
277 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_sync_result:\t%d\n", result);
278 GNUNET_assert (GNUNET_OK == result);
280 modifiers[0] = (struct GNUNET_ENV_Modifier) {
283 .value = "one two three",
284 .value_size = sizeof ("one two three") - 1
286 modifiers[1] = (struct GNUNET_ENV_Modifier) {
289 .value = "four five six",
290 .value_size = sizeof ("four five six") - 1
293 op = GNUNET_PSYCSTORE_state_modify (h, &channel_pub_key,
294 GNUNET_ntohll (fcls->msg[0]->message_id), 0,
295 2, modifiers, state_modify_result, fcls);
300 fragment_result (void *cls,
301 struct GNUNET_MULTICAST_MessageHeader *msg,
302 enum GNUNET_PSYCSTORE_MessageFlags flags)
304 struct FragmentClosure *fcls = cls;
305 struct GNUNET_MULTICAST_MessageHeader *msg0 = fcls->msg[fcls->n];
306 uint64_t flags0 = fcls->flags[fcls->n++];
308 if (flags == flags0 && msg->header.size == msg0->header.size
309 && 0 == memcmp (msg, msg0, ntohs (msg->header.size)))
311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " fragment %llu matches\n",
312 GNUNET_ntohll (msg->fragment_id));
317 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " fragment %llu differs\n",
318 GNUNET_ntohll (msg->fragment_id));
320 return GNUNET_SYSERR;
326 message_get_result (void *cls, int64_t result, const char *err_msg)
328 struct FragmentClosure *fcls = cls;
330 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get:\t%d\n", result);
331 GNUNET_assert (result > 0 && fcls->n && fcls->n_expected);
334 modifiers[0] = (struct GNUNET_ENV_Modifier) {
337 .value = "three two one",
338 .value_size = sizeof ("three two one") - 1
340 modifiers[1] = (struct GNUNET_ENV_Modifier) {
343 .value = "ten eleven twelve",
344 .value_size = sizeof ("ten eleven twelve") - 1
347 op = GNUNET_PSYCSTORE_state_sync (h, &channel_pub_key,
348 GNUNET_ntohll (fcls->msg[0]->message_id) + 1,
349 2, modifiers, state_sync_result, fcls);
354 message_get_fragment_result (void *cls, int64_t result, const char *err_msg)
356 struct FragmentClosure *fcls = cls;
358 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_fragment:\t%d\n", result);
359 GNUNET_assert (result > 0 && fcls->n && fcls->n_expected);
362 fcls->n_expected = 3;
363 op = GNUNET_PSYCSTORE_message_get (h, &channel_pub_key, &slave_pub_key,
364 GNUNET_ntohll (fcls->msg[0]->message_id),
366 &message_get_result, fcls);
371 fragment_get_result (void *cls, int64_t result, const char *err_msg)
373 struct FragmentClosure *fcls = cls;
375 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_get:\t%d\n", result);
376 GNUNET_assert (result > 0 && fcls->n && fcls->n_expected);
379 fcls->n_expected = 2;
380 op = GNUNET_PSYCSTORE_message_get_fragment (h, &channel_pub_key, &slave_pub_key,
381 GNUNET_ntohll (fcls->msg[1]->message_id),
382 GNUNET_ntohll (fcls->msg[1]->fragment_offset),
384 &message_get_fragment_result,
391 fragment_store_result (void *cls, int64_t result, const char *err_msg)
394 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_store:\t%d\n", result);
395 GNUNET_assert (GNUNET_OK == result);
397 if ((intptr_t) cls == GNUNET_YES)
398 { /* last fragment */
401 op = GNUNET_PSYCSTORE_fragment_get (h, &channel_pub_key, &slave_pub_key,
402 GNUNET_ntohll (fcls.msg[0]->fragment_id),
404 &fragment_get_result, &fcls);
412 struct GNUNET_MULTICAST_MessageHeader *msg;
413 fcls.flags[0] = GNUNET_PSYCSTORE_MESSAGE_STATE;
414 fcls.msg[0] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
415 GNUNET_assert (msg != NULL);
417 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
418 msg->header.size = htons (sizeof (*msg) + sizeof (channel_pub_key));
420 msg->hop_counter = htonl (9);
421 msg->fragment_id = GNUNET_htonll (INT64_MAX - 8);
422 msg->fragment_offset = GNUNET_htonll (0);
423 msg->message_id = GNUNET_htonll (INT64_MAX - 10);
424 msg->group_generation = GNUNET_htonll (INT64_MAX - 3);
425 msg->flags = htonl (GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT);
427 memcpy (&msg[1], &channel_pub_key, sizeof (channel_pub_key));
429 msg->purpose.size = htonl (ntohs (msg->header.size)
430 - sizeof (msg->header)
431 - sizeof (msg->hop_counter)
432 - sizeof (msg->signature));
433 msg->purpose.purpose = htonl (234);
434 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (channel_key, &msg->purpose,
437 op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[0],
438 &fragment_store_result, GNUNET_NO);
440 fcls.flags[1] = GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED;
441 fcls.msg[1] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
442 memcpy (msg, fcls.msg[0], sizeof (*msg) + sizeof (channel_pub_key));
443 msg->fragment_id = GNUNET_htonll (INT64_MAX - 4);
444 msg->fragment_offset = GNUNET_htonll (1024);
446 op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[1],
447 &fragment_store_result, GNUNET_NO);
449 fcls.flags[2] = GNUNET_PSYCSTORE_MESSAGE_STATE_HASH;
450 fcls.msg[2] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
451 memcpy (msg, fcls.msg[1], sizeof (*msg) + sizeof (channel_pub_key));
452 msg->fragment_id = GNUNET_htonll (INT64_MAX);
453 msg->fragment_offset = GNUNET_htonll (16384);
455 op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[2],
456 &fragment_store_result, (void *) GNUNET_YES);
461 membership_test_result (void *cls, int64_t result, const char *err_msg)
464 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_test:\t%d\n", result);
465 GNUNET_assert (GNUNET_OK == result);
472 membership_store_result (void *cls, int64_t result, const char *err_msg)
475 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_store:\t%d\n", result);
476 GNUNET_assert (GNUNET_OK == result);
478 op = GNUNET_PSYCSTORE_membership_test (h, &channel_pub_key, &slave_pub_key,
480 &membership_test_result, NULL);
484 * Main function of the test, run from scheduler.
487 * @param cfg configuration we use (also to connect to PSYCstore service)
488 * @param peer handle to access more of the peer (not used)
491 #if DEBUG_TEST_PSYCSTORE
492 run (void *cls, char *const *args, const char *cfgfile,
493 const struct GNUNET_CONFIGURATION_Handle *cfg)
496 const struct GNUNET_CONFIGURATION_Handle *cfg,
497 struct GNUNET_TESTING_Peer *peer)
500 end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
502 h = GNUNET_PSYCSTORE_connect (cfg);
503 GNUNET_assert (NULL != h);
505 channel_key = GNUNET_CRYPTO_eddsa_key_create ();
506 slave_key = GNUNET_CRYPTO_ecdsa_key_create ();
508 GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
509 GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);
511 op = GNUNET_PSYCSTORE_membership_store (h, &channel_pub_key, &slave_pub_key,
512 GNUNET_YES, INT64_MAX - 5,
514 &membership_store_result, NULL);
519 main (int argc, char *argv[])
522 #if DEBUG_TEST_PSYCSTORE
523 const struct GNUNET_GETOPT_CommandLineOption opts[] = {
524 GNUNET_GETOPT_OPTION_END
526 if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-psycstore",
527 "test-psycstore [options]",
531 if (0 != GNUNET_TESTING_service_run ("test-psycstore", "psycstore",
532 "test_psycstore.conf", &run, NULL))
538 /* end of test_psycstore.c */