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 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.
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.
16 * @file datastore/test_datastore_api.c
17 * @brief Test for the basic datastore API.
18 * @author Christian Grothoff
21 * - test reservation failure
25 #include "gnunet_util_lib.h"
26 #include "gnunet_protocols.h"
27 #include "gnunet_datastore_service.h"
28 #include "gnunet_datastore_plugin.h"
29 #include "gnunet_testing_lib.h"
33 * How long until we give up on transmitting the message?
35 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
37 #define ITERATIONS 256
40 * Handle to the datastore.
42 static struct GNUNET_DATASTORE_Handle *datastore;
44 static struct GNUNET_TIME_Absolute now;
47 * Value we return from #main().
52 * Name of plugin under test.
54 static const char *plugin_name;
67 static char buf[60000];
69 memset (buf, i, 8 * i);
95 static struct GNUNET_TIME_Absolute
96 get_expiration (int i)
98 struct GNUNET_TIME_Absolute av;
100 av.abs_value_us = now.abs_value_us + 20000000000LL - i * 1000 * 1000LL;
106 * Which phase of the process are we in?
111 * We are done (shutting down normally).
116 * We are adding new entries to the datastore.
125 RP_PUT_MULTIPLE_NEXT = 8,
127 RP_GET_MULTIPLE_NEXT = 10,
130 * Execution failed with some kind of error.
137 * Closure we give to all of the functions executing the
138 * benchmark. Could right now be global, but this allows
139 * us to theoretically run multiple clients "in parallel".
144 * Execution phase we are in.
148 struct GNUNET_HashCode key;
159 * Main state machine. Executes the next step of the test
160 * depending on the current state.
162 * @param cls the `struct CpsRunContext`
165 run_continuation (void *cls);
169 * Continuation called to notify client about result of an
170 * operation. Checks for errors, updates our iteration counters and
171 * continues execution with #run_continuation().
173 * @param cls the `struct CpsRunContext`
174 * @param success #GNUNET_SYSERR on failure
175 * @param min_expiration minimum expiration time required for content to be stored
176 * by the datacache at this time, zero for unknown
177 * @param msg NULL on success, otherwise an error message
180 check_success (void *cls,
182 struct GNUNET_TIME_Absolute min_expiration,
185 struct CpsRunContext *crc = cls;
187 if (GNUNET_OK != success)
189 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
190 "Operation %d/%d not successful: `%s'\n",
194 crc->phase = RP_ERROR;
196 GNUNET_free_non_null (crc->data);
198 GNUNET_SCHEDULER_add_now (&run_continuation, crc);
203 get_reserved (void *cls,
205 struct GNUNET_TIME_Absolute min_expiration,
208 struct CpsRunContext *crc = cls;
211 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
212 "Error obtaining reservation: `%s'\n",
214 GNUNET_assert (0 < success);
216 GNUNET_SCHEDULER_add_now (&run_continuation,
222 check_value (void *cls,
223 const struct GNUNET_HashCode *key,
226 enum GNUNET_BLOCK_Type type,
229 uint32_t replication,
230 struct GNUNET_TIME_Absolute expiration,
233 struct CpsRunContext *crc = cls;
239 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
240 "Value check failed (got NULL key) in %d/%d\n",
243 crc->phase = RP_ERROR;
244 GNUNET_SCHEDULER_add_now (&run_continuation,
250 "Check value got `%s' of size %u, type %d, expire %s\n",
251 GNUNET_h2s (key), (unsigned int) size, type,
252 GNUNET_STRINGS_absolute_time_to_string (expiration));
254 "Check value iteration %d wants size %u, type %d, expire %s\n", i,
255 (unsigned int) get_size (i), get_type (i),
256 GNUNET_STRINGS_absolute_time_to_string (get_expiration(i)));
258 GNUNET_assert (size == get_size (i));
259 GNUNET_assert (0 == memcmp (data, get_data (i), size));
260 GNUNET_assert (type == get_type (i));
261 GNUNET_assert (priority == get_priority (i));
262 GNUNET_assert (anonymity == get_anonymity (i));
263 GNUNET_assert (expiration.abs_value_us == get_expiration (i).abs_value_us);
269 GNUNET_SCHEDULER_add_now (&run_continuation,
275 delete_value (void *cls,
276 const struct GNUNET_HashCode *key,
279 enum GNUNET_BLOCK_Type type,
282 uint32_t replication,
283 struct GNUNET_TIME_Absolute expiration,
286 struct CpsRunContext *crc = cls;
288 GNUNET_assert (NULL == crc->data);
289 GNUNET_assert (NULL != key);
292 crc->data = GNUNET_malloc (size);
293 GNUNET_memcpy (crc->data, data, size);
294 crc->phase = RP_DO_DEL;
295 GNUNET_SCHEDULER_add_now (&run_continuation,
301 check_nothing (void *cls,
302 const struct GNUNET_HashCode *key,
305 enum GNUNET_BLOCK_Type type,
308 uint32_t replication,
309 struct GNUNET_TIME_Absolute expiration,
312 struct CpsRunContext *crc = cls;
314 GNUNET_assert (key == NULL);
316 crc->phase = RP_RESERVE;
317 GNUNET_SCHEDULER_add_now (&run_continuation,
323 check_multiple (void *cls,
324 const struct GNUNET_HashCode *key,
327 enum GNUNET_BLOCK_Type type,
330 uint32_t replication,
331 struct GNUNET_TIME_Absolute expiration,
334 struct CpsRunContext *crc = cls;
336 GNUNET_assert (key != NULL);
339 case RP_GET_MULTIPLE:
340 crc->phase = RP_GET_MULTIPLE_NEXT;
341 crc->first_uid = uid;
343 case RP_GET_MULTIPLE_NEXT:
344 GNUNET_assert (uid != crc->first_uid);
345 crc->phase = RP_DONE;
349 crc->phase = RP_ERROR;
352 GNUNET_SCHEDULER_add_now (&run_continuation, crc);
357 * Main state machine. Executes the next step of the test
358 * depending on the current state.
360 * @param cls the `struct CpsRunContext`
363 run_continuation (void *cls)
365 struct CpsRunContext *crc = cls;
367 ok = (int) crc->phase;
368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
369 "Test in phase %u\n",
374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
375 "Executing PUT number %u\n",
377 GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
378 GNUNET_DATASTORE_put (datastore, 0, &crc->key, get_size (crc->i),
379 get_data (crc->i), get_type (crc->i),
380 get_priority (crc->i), get_anonymity (crc->i), 0,
381 get_expiration (crc->i), 1, 1,
382 &check_success, crc);
384 if (crc->i == ITERATIONS)
389 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
390 "Executing GET number %u\n",
392 GNUNET_CRYPTO_hash (&crc->i,
395 GNUNET_DATASTORE_get_key (datastore,
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
408 "Executing DEL number %u\n",
411 GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
412 GNUNET_assert (NULL !=
413 GNUNET_DATASTORE_get_key (datastore,
424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
425 "Executing DO_DEL number %u\n",
430 crc->phase = RP_DELVALIDATE;
436 GNUNET_assert (NULL !=
437 GNUNET_DATASTORE_remove (datastore, &crc->key, crc->size,
439 &check_success, crc));
443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
444 "Executing DELVALIDATE number %u\n",
446 GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
447 GNUNET_assert (NULL !=
448 GNUNET_DATASTORE_get_key (datastore,
459 crc->phase = RP_PUT_MULTIPLE;
460 GNUNET_DATASTORE_reserve (datastore, 128 * 1024, 2,
463 case RP_PUT_MULTIPLE:
464 crc->phase = RP_PUT_MULTIPLE_NEXT;
465 GNUNET_DATASTORE_put (datastore, crc->rid, &crc->key, get_size (42),
466 get_data (42), get_type (42), get_priority (42),
467 get_anonymity (42), 0, get_expiration (42), 1, 1,
468 &check_success, crc);
470 case RP_PUT_MULTIPLE_NEXT:
471 crc->phase = RP_GET_MULTIPLE;
472 GNUNET_DATASTORE_put (datastore, crc->rid,
482 &check_success, crc);
484 case RP_GET_MULTIPLE:
485 GNUNET_assert (NULL !=
486 GNUNET_DATASTORE_get_key (datastore,
496 case RP_GET_MULTIPLE_NEXT:
497 GNUNET_assert (NULL !=
498 GNUNET_DATASTORE_get_key (datastore,
509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
510 "Finished, disconnecting\n");
511 GNUNET_DATASTORE_disconnect (datastore,
517 GNUNET_DATASTORE_disconnect (datastore,
527 * Function called with the result of the initial PUT operation. If
528 * the PUT succeeded, we start the actual benchmark loop, otherwise we
529 * bail out with an error.
533 * @param success #GNUNET_SYSERR on failure
534 * @param min_expiration minimum expiration time required for content to be stored
535 * by the datacache at this time, zero for unknown
536 * @param msg NULL on success, otherwise an error message
539 run_tests (void *cls,
541 struct GNUNET_TIME_Absolute min_expiration,
544 struct CpsRunContext *crc = cls;
549 GNUNET_SCHEDULER_add_now (&run_continuation,
554 "%s", "Test 'put' operation failed, key already exists (!?)\n");
555 GNUNET_DATASTORE_disconnect (datastore,
561 "Test 'put' operation failed with error `%s' database likely not setup, skipping test.\n",
563 GNUNET_DATASTORE_disconnect (datastore,
574 * Beginning of the actual execution of the benchmark.
575 * Performs a first test operation (PUT) to verify that
576 * the plugin works at all.
579 * @param cfg configuration to use
580 * @param peer peer handle (unused)
584 const struct GNUNET_CONFIGURATION_Handle *cfg,
585 struct GNUNET_TESTING_Peer *peer)
587 struct CpsRunContext *crc;
588 static struct GNUNET_HashCode zkey;
590 crc = GNUNET_new (struct CpsRunContext);
592 now = GNUNET_TIME_absolute_get ();
593 datastore = GNUNET_DATASTORE_connect (cfg);
595 GNUNET_DATASTORE_put (datastore,
600 GNUNET_BLOCK_TYPE_TEST,
602 GNUNET_TIME_relative_to_absolute
603 (GNUNET_TIME_UNIT_SECONDS),
609 "Test 'put' operation failed.\n");
617 * Function invoked to notify service of disk utilization
621 * @param delta change in disk utilization,
622 * 0 for "reset to empty"
625 duc_dummy (void *cls,
628 /* intentionally empty */
633 * check if plugin is actually working
636 test_plugin (const char *cfg_name)
639 struct GNUNET_CONFIGURATION_Handle *cfg;
640 struct GNUNET_DATASTORE_PluginFunctions *api;
641 struct GNUNET_DATASTORE_PluginEnvironment env;
643 cfg = GNUNET_CONFIGURATION_create ();
645 GNUNET_CONFIGURATION_load (cfg,
648 GNUNET_CONFIGURATION_destroy (cfg);
650 "Failed to load configuration %s\n",
654 memset (&env, 0, sizeof (env));
656 env.duc = &duc_dummy;
657 GNUNET_snprintf (libname,
659 "libgnunet_plugin_datastore_%s",
661 api = GNUNET_PLUGIN_load (libname, &env);
664 GNUNET_CONFIGURATION_destroy (cfg);
666 "Failed to load plugin `%s'\n",
670 GNUNET_PLUGIN_unload (libname, api);
671 GNUNET_CONFIGURATION_destroy (cfg);
677 * Entry point into the test. Determines which configuration / plugin
678 * we are running with based on the name of the binary and starts
681 * @param argc should be 1
682 * @param argv used to determine plugin / configuration name.
683 * @return 0 on success
692 plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
693 GNUNET_snprintf (cfg_name,
695 "test_datastore_api_data_%s.conf",
697 ret = test_plugin (cfg_name);
700 /* run actual test */
702 GNUNET_TESTING_peer_run ("test-gnunet-datastore",
710 /* end of test_datastore_api.c */