2 This file is part of GNUnet.
3 Copyright (C) 2004, 2005, 2006, 2007, 2009, 2015 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 * @file datastore/test_datastore_api.c
22 * @brief Test for the basic datastore API.
23 * @author Christian Grothoff
26 * - test reservation failure
30 #include "gnunet_util_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_datastore_service.h"
33 #include "gnunet_datastore_plugin.h"
34 #include "gnunet_testing_lib.h"
38 * How long until we give up on transmitting the message?
40 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
42 #define ITERATIONS 256
45 * Handle to the datastore.
47 static struct GNUNET_DATASTORE_Handle *datastore;
49 static struct GNUNET_TIME_Absolute now;
52 * Value we return from #main().
57 * Name of plugin under test.
59 static const char *plugin_name;
72 static char buf[60000];
74 memset (buf, i, 8 * i);
100 static struct GNUNET_TIME_Absolute
101 get_expiration (int i)
103 struct GNUNET_TIME_Absolute av;
105 av.abs_value_us = now.abs_value_us + 20000000000LL - i * 1000 * 1000LL;
111 * Which phase of the process are we in?
116 * We are done (shutting down normally).
121 * We are adding new entries to the datastore.
130 RP_PUT_MULTIPLE_NEXT = 8,
132 RP_GET_MULTIPLE_NEXT = 10,
135 * Execution failed with some kind of error.
142 * Closure we give to all of the functions executing the
143 * benchmark. Could right now be global, but this allows
144 * us to theoretically run multiple clients "in parallel".
149 * Execution phase we are in.
153 struct GNUNET_HashCode key;
166 * Main state machine. Executes the next step of the test
167 * depending on the current state.
169 * @param cls the `struct CpsRunContext`
172 run_continuation (void *cls);
176 * Continuation called to notify client about result of an
177 * operation. Checks for errors, updates our iteration counters and
178 * continues execution with #run_continuation().
180 * @param cls the `struct CpsRunContext`
181 * @param success #GNUNET_SYSERR on failure
182 * @param min_expiration minimum expiration time required for content to be stored
183 * by the datacache at this time, zero for unknown
184 * @param msg NULL on success, otherwise an error message
187 check_success (void *cls,
189 struct GNUNET_TIME_Absolute min_expiration,
192 struct CpsRunContext *crc = cls;
194 if (GNUNET_OK != success)
196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
197 "Operation %d/%d not successful: `%s'\n",
201 crc->phase = RP_ERROR;
203 GNUNET_free_non_null (crc->data);
205 GNUNET_SCHEDULER_add_now (&run_continuation, crc);
210 get_reserved (void *cls,
212 struct GNUNET_TIME_Absolute min_expiration,
215 struct CpsRunContext *crc = cls;
218 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
219 "Error obtaining reservation: `%s'\n",
221 GNUNET_assert (0 < success);
223 GNUNET_SCHEDULER_add_now (&run_continuation,
229 check_value (void *cls,
230 const struct GNUNET_HashCode *key,
233 enum GNUNET_BLOCK_Type type,
236 struct GNUNET_TIME_Absolute expiration,
239 struct CpsRunContext *crc = cls;
245 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
246 "Value check failed (got NULL key) in %d/%d\n",
249 crc->phase = RP_ERROR;
250 GNUNET_SCHEDULER_add_now (&run_continuation,
256 "Check value got `%s' of size %u, type %d, expire %s\n",
257 GNUNET_h2s (key), (unsigned int) size, type,
258 GNUNET_STRINGS_absolute_time_to_string (expiration));
260 "Check value iteration %d wants size %u, type %d, expire %s\n", i,
261 (unsigned int) get_size (i), get_type (i),
262 GNUNET_STRINGS_absolute_time_to_string (get_expiration(i)));
264 GNUNET_assert (size == get_size (i));
265 GNUNET_assert (0 == memcmp (data, get_data (i), size));
266 GNUNET_assert (type == get_type (i));
267 GNUNET_assert (priority == get_priority (i));
268 GNUNET_assert (anonymity == get_anonymity (i));
269 GNUNET_assert (expiration.abs_value_us == get_expiration (i).abs_value_us);
276 GNUNET_SCHEDULER_add_now (&run_continuation,
282 delete_value (void *cls,
283 const struct GNUNET_HashCode *key,
286 enum GNUNET_BLOCK_Type type,
289 struct GNUNET_TIME_Absolute expiration,
292 struct CpsRunContext *crc = cls;
294 GNUNET_assert (NULL == crc->data);
295 GNUNET_assert (NULL != key);
298 crc->data = GNUNET_malloc (size);
299 GNUNET_memcpy (crc->data, data, size);
300 crc->phase = RP_DO_DEL;
301 GNUNET_SCHEDULER_add_now (&run_continuation,
307 check_nothing (void *cls,
308 const struct GNUNET_HashCode *key,
311 enum GNUNET_BLOCK_Type type,
314 struct GNUNET_TIME_Absolute expiration,
317 struct CpsRunContext *crc = cls;
319 GNUNET_assert (key == NULL);
321 crc->phase = RP_RESERVE;
322 GNUNET_SCHEDULER_add_now (&run_continuation,
328 check_multiple (void *cls,
329 const struct GNUNET_HashCode *key,
332 enum GNUNET_BLOCK_Type type,
335 struct GNUNET_TIME_Absolute expiration,
338 struct CpsRunContext *crc = cls;
340 GNUNET_assert (key != NULL);
343 case RP_GET_MULTIPLE:
344 crc->phase = RP_GET_MULTIPLE_NEXT;
345 crc->first_uid = uid;
348 case RP_GET_MULTIPLE_NEXT:
349 GNUNET_assert (uid != crc->first_uid);
350 crc->phase = RP_DONE;
354 crc->phase = RP_ERROR;
357 if (priority == get_priority (42))
359 GNUNET_SCHEDULER_add_now (&run_continuation, crc);
364 * Main state machine. Executes the next step of the test
365 * depending on the current state.
367 * @param cls the `struct CpsRunContext`
370 run_continuation (void *cls)
372 struct CpsRunContext *crc = cls;
374 ok = (int) crc->phase;
375 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
376 "Test in phase %u\n",
381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
382 "Executing PUT number %u\n",
384 GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
385 GNUNET_DATASTORE_put (datastore, 0, &crc->key, get_size (crc->i),
386 get_data (crc->i), get_type (crc->i),
387 get_priority (crc->i), get_anonymity (crc->i), 0,
388 get_expiration (crc->i), 1, 1,
389 &check_success, crc);
391 if (crc->i == ITERATIONS)
396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
397 "Executing GET number %u\n",
399 GNUNET_CRYPTO_hash (&crc->i,
402 GNUNET_DATASTORE_get_key (datastore,
413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
414 "Executing DEL number %u\n",
417 GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
418 GNUNET_assert (NULL !=
419 GNUNET_DATASTORE_get_key (datastore,
429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
430 "Executing DO_DEL number %u\n",
435 crc->phase = RP_DELVALIDATE;
441 GNUNET_assert (NULL !=
442 GNUNET_DATASTORE_remove (datastore, &crc->key, crc->size,
444 &check_success, crc));
448 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
449 "Executing DELVALIDATE number %u\n",
451 GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
452 GNUNET_assert (NULL !=
453 GNUNET_DATASTORE_get_key (datastore, crc->offset, &crc->key,
454 get_type (crc->i), 1, 1,
455 &check_nothing, crc));
458 crc->phase = RP_PUT_MULTIPLE;
459 GNUNET_DATASTORE_reserve (datastore, 128 * 1024, 2,
462 case RP_PUT_MULTIPLE:
463 crc->phase = RP_PUT_MULTIPLE_NEXT;
464 GNUNET_DATASTORE_put (datastore, crc->rid, &crc->key, get_size (42),
465 get_data (42), get_type (42), get_priority (42),
466 get_anonymity (42), 0, get_expiration (42), 1, 1,
467 &check_success, crc);
469 case RP_PUT_MULTIPLE_NEXT:
470 crc->phase = RP_GET_MULTIPLE;
471 GNUNET_DATASTORE_put (datastore, crc->rid,
481 &check_success, crc);
483 case RP_GET_MULTIPLE:
484 GNUNET_assert (NULL !=
485 GNUNET_DATASTORE_get_key (datastore,
489 &check_multiple, crc));
491 case RP_GET_MULTIPLE_NEXT:
492 GNUNET_assert (NULL !=
493 GNUNET_DATASTORE_get_key (datastore,
498 &check_multiple, crc));
501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
502 "Finished, disconnecting\n");
503 GNUNET_DATASTORE_disconnect (datastore,
509 GNUNET_DATASTORE_disconnect (datastore,
519 * Function called with the result of the initial PUT operation. If
520 * the PUT succeeded, we start the actual benchmark loop, otherwise we
521 * bail out with an error.
525 * @param success #GNUNET_SYSERR on failure
526 * @param min_expiration minimum expiration time required for content to be stored
527 * by the datacache at this time, zero for unknown
528 * @param msg NULL on success, otherwise an error message
531 run_tests (void *cls,
533 struct GNUNET_TIME_Absolute min_expiration,
536 struct CpsRunContext *crc = cls;
541 GNUNET_SCHEDULER_add_now (&run_continuation,
546 "%s", "Test 'put' operation failed, key already exists (!?)\n");
547 GNUNET_DATASTORE_disconnect (datastore,
553 "Test 'put' operation failed with error `%s' database likely not setup, skipping test.\n",
555 GNUNET_DATASTORE_disconnect (datastore,
566 * Beginning of the actual execution of the benchmark.
567 * Performs a first test operation (PUT) to verify that
568 * the plugin works at all.
571 * @param cfg configuration to use
572 * @param peer peer handle (unused)
576 const struct GNUNET_CONFIGURATION_Handle *cfg,
577 struct GNUNET_TESTING_Peer *peer)
579 struct CpsRunContext *crc;
580 static struct GNUNET_HashCode zkey;
582 crc = GNUNET_new (struct CpsRunContext);
584 now = GNUNET_TIME_absolute_get ();
585 datastore = GNUNET_DATASTORE_connect (cfg);
587 GNUNET_DATASTORE_put (datastore,
592 GNUNET_BLOCK_TYPE_TEST,
594 GNUNET_TIME_relative_to_absolute
595 (GNUNET_TIME_UNIT_SECONDS),
601 "Test 'put' operation failed.\n");
609 * Function invoked to notify service of disk utilization
613 * @param delta change in disk utilization,
614 * 0 for "reset to empty"
617 duc_dummy (void *cls,
620 /* intentionally empty */
625 * check if plugin is actually working
628 test_plugin (const char *cfg_name)
631 struct GNUNET_CONFIGURATION_Handle *cfg;
632 struct GNUNET_DATASTORE_PluginFunctions *api;
633 struct GNUNET_DATASTORE_PluginEnvironment env;
635 cfg = GNUNET_CONFIGURATION_create ();
637 GNUNET_CONFIGURATION_load (cfg,
640 GNUNET_CONFIGURATION_destroy (cfg);
642 "Failed to load configuration %s\n",
646 memset (&env, 0, sizeof (env));
648 env.duc = &duc_dummy;
649 GNUNET_snprintf (libname,
651 "libgnunet_plugin_datastore_%s",
653 api = GNUNET_PLUGIN_load (libname, &env);
656 GNUNET_CONFIGURATION_destroy (cfg);
658 "Failed to load plugin `%s'\n",
662 GNUNET_PLUGIN_unload (libname, api);
663 GNUNET_CONFIGURATION_destroy (cfg);
669 * Entry point into the test. Determines which configuration / plugin
670 * we are running with based on the name of the binary and starts
673 * @param argc should be 1
674 * @param argv used to determine plugin / configuration name.
675 * @return 0 on success
684 plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
685 GNUNET_snprintf (cfg_name,
687 "test_datastore_api_data_%s.conf",
689 ret = test_plugin (cfg_name);
692 /* run actual test */
694 GNUNET_TESTING_peer_run ("test-gnunet-datastore",
702 /* end of test_datastore_api.c */