From: Christian Grothoff Date: Sat, 25 Jul 2009 14:30:10 +0000 (+0000) Subject: more tests X-Git-Tag: initial-import-from-subversion-38251~23634 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=4f3705cbfef52322292ce8b60f1d5326825f8606;p=oweals%2Fgnunet.git more tests --- diff --git a/src/datastore/Makefile.am b/src/datastore/Makefile.am index 17fdb4378..07a14e534 100644 --- a/src/datastore/Makefile.am +++ b/src/datastore/Makefile.am @@ -58,6 +58,7 @@ libgnunet_plugin_datastore_template_la_LDFLAGS = \ check_PROGRAMS = \ test_datastore_api \ + test_datastore_api_management \ perf_datastore_api \ perf_plugin_datastore @@ -69,6 +70,12 @@ test_datastore_api_LDADD = \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la +test_datastore_api_management_SOURCES = \ + test_datastore_api_management.c +test_datastore_api_management_LDADD = \ + $(top_builddir)/src/datastore/libgnunetdatastore.la \ + $(top_builddir)/src/util/libgnunetutil.la + perf_datastore_api_SOURCES = \ perf_datastore_api.c perf_datastore_api_LDADD = \ diff --git a/src/datastore/datastore.h b/src/datastore/datastore.h index f1da17ee4..aa2646c0a 100644 --- a/src/datastore/datastore.h +++ b/src/datastore/datastore.h @@ -19,7 +19,7 @@ */ /** - * @file datastore/datastore.hc + * @file datastore/datastore.h * @brief structs for communication between datastore service and API * @author Christian Grothoff */ diff --git a/src/datastore/datastore_api.c b/src/datastore/datastore_api.c index f9a28800c..361f76e4a 100644 --- a/src/datastore/datastore_api.c +++ b/src/datastore/datastore_api.c @@ -204,16 +204,21 @@ with_status_response_handler (void *cls, sm = (const struct StatusMessage*) msg; status = ntohl(sm->status); emsg = NULL; - if (status == GNUNET_SYSERR) + if (ntohs(msg->size) > sizeof(struct StatusMessage)) { emsg = (const char*) &sm[1]; - if ( (ntohs(msg->size) == sizeof(struct StatusMessage)) || - (emsg[ntohs(msg->size) - sizeof(struct StatusMessage) - 1] != '\0') ) + if (emsg[ntohs(msg->size) - sizeof(struct StatusMessage) - 1] != '\0') { GNUNET_break (0); emsg = _("Invalid error message received from datastore service"); } } + if ( (status == GNUNET_SYSERR) && + (emsg == NULL) ) + { + GNUNET_break (0); + emsg = _("Invalid error message received from datastore service"); + } h->response_proc = NULL; #if DEBUG_DATASTORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -408,7 +413,7 @@ GNUNET_DATASTORE_reserve (struct GNUNET_DATASTORE_Handle *h, rm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE); rm->header.size = htons(sizeof (struct ReserveMessage)); rm->entries = htonl(entries); - rm->amount = htonl(amount); + rm->amount = GNUNET_htonll(amount); transmit_for_status (h, cont, cont_cls, timeout); } diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c index 77047dc8a..22ae6feb5 100644 --- a/src/datastore/gnunet-service-datastore.c +++ b/src/datastore/gnunet-service-datastore.c @@ -513,7 +513,7 @@ transmit_status (struct GNUNET_SERVER_Client *client, #if DEBUG_DATASTORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmitting `%s' message with value %d and message %s\n", + "Transmitting `%s' message with value %d and message `%s'\n", "STATUS", code, msg != NULL ? msg : "(none)"); @@ -639,15 +639,15 @@ handle_reserve (void *cls, unsigned long long used; unsigned long long req; uint64_t amount; - uint64_t entries; + uint32_t entries; #if DEBUG_DATASTORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request\n", "RESERVE"); #endif - amount = ntohl(msg->amount); - entries = GNUNET_ntohll(msg->entries); + amount = GNUNET_ntohll(msg->amount); + entries = ntohl(msg->entries); used = plugin->api->get_size (plugin->api->cls) + reserved; req = amount + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * entries; if (used + req > quota) diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c index 9a807463a..af4dcc322 100644 --- a/src/datastore/plugin_datastore_sqlite.c +++ b/src/datastore/plugin_datastore_sqlite.c @@ -29,7 +29,7 @@ #include "plugin_datastore.h" #include -#define DEBUG_SQLITE GNUNET_YES +#define DEBUG_SQLITE GNUNET_NO /** * After how many payload-changing operations @@ -44,7 +44,7 @@ * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ -#define LOG_SQLITE(db, msg, level, cmd) do { GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); if (msg != NULL) GNUNET_asprintf(msg, _("`%s' failed with error: %s\n"), cmd, sqlite3_errmsg(db->dbh)); } while(0) +#define LOG_SQLITE(db, msg, level, cmd) do { GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); if (msg != NULL) GNUNET_asprintf(msg, _("`%s' failed with error: %s"), cmd, sqlite3_errmsg(db->dbh)); } while(0) #define SELECT_IT_LOW_PRIORITY_1 \ "SELECT size,type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn080 WHERE (prio = ? AND hash > ?) "\ @@ -768,7 +768,7 @@ sqlite_plugin_update (void *cls, sqlite3_bind_int64 (plugin->updPrio, 2, expire.value); sqlite3_bind_int64 (plugin->updPrio, 3, uid); n = sqlite3_step (plugin->updPrio); - if (n != SQLITE_OK) + if (n != SQLITE_DONE) LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); @@ -782,7 +782,7 @@ sqlite_plugin_update (void *cls, if (n == SQLITE_BUSY) return GNUNET_NO; - return n == SQLITE_OK ? GNUNET_OK : GNUNET_SYSERR; + return n == SQLITE_DONE ? GNUNET_OK : GNUNET_SYSERR; } diff --git a/src/datastore/test_datastore_api.c b/src/datastore/test_datastore_api.c index 3d65bf813..005c11a58 100644 --- a/src/datastore/test_datastore_api.c +++ b/src/datastore/test_datastore_api.c @@ -19,13 +19,11 @@ */ /* * @file datastore/test_datastore_api.c - * @brief Test for the datastore implementation. + * @brief Test for the basic datastore API. * @author Christian Grothoff * * TODO: - * - test multiple values under same key - * - test "update" - * - test storage reservations + * - test reservation failure */ #include "platform.h" @@ -91,7 +89,7 @@ get_expiration (int i) { struct GNUNET_TIME_Absolute av; - av.value = now.value - i * 1000; + av.value = now.value + 200000 - i * 1000; return av; } @@ -102,7 +100,16 @@ enum RunPhase RP_GET, RP_DEL, RP_DO_DEL, - RP_DELVALIDATE + RP_DELVALIDATE, + RP_RESERVE, + RP_PUT_MULTIPLE, + RP_PUT_MULTIPLE_NEXT, + RP_GET_MULTIPLE, + RP_GET_MULTIPLE_NEXT, + RP_GET_MULTIPLE_DONE, + RP_UPDATE, + RP_UPDATE_VALIDATE, + RP_UPDATE_DONE }; @@ -110,12 +117,14 @@ struct CpsRunContext { GNUNET_HashCode key; int i; + int rid; int *iptr; struct GNUNET_SCHEDULER_Handle *sched; struct GNUNET_CONFIGURATION_Handle *cfg; void *data; size_t size; enum RunPhase phase; + unsigned long long uid; }; @@ -144,6 +153,25 @@ check_success (void *cls, } +static void +get_reserved (void *cls, + int success, + const char *msg) +{ + struct CpsRunContext *crc = cls; + if (0 >= success) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "%s\n", msg); + GNUNET_assert (0 < success); + crc->rid = success; + GNUNET_SCHEDULER_add_continuation (crc->sched, + GNUNET_NO, + &run_continuation, + crc, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); +} + + static void check_value (void *cls, const GNUNET_HashCode * key, @@ -227,7 +255,7 @@ check_nothing (void *cls, GNUNET_assert (key == NULL); if (crc->i == 0) { - crc->phase = RP_DONE; + crc->phase = RP_RESERVE; } GNUNET_SCHEDULER_add_continuation (crc->sched, GNUNET_NO, @@ -237,12 +265,81 @@ check_nothing (void *cls, } +static void +check_multiple (void *cls, + const GNUNET_HashCode * key, + uint32_t size, + const void *data, + uint32_t type, + uint32_t priority, + uint32_t anonymity, + struct GNUNET_TIME_Absolute + expiration, uint64_t uid) +{ + struct CpsRunContext *crc = cls; + + if (key == NULL) + { + GNUNET_assert (crc->phase == RP_GET_MULTIPLE_DONE); + crc->phase = RP_UPDATE; + GNUNET_SCHEDULER_add_continuation (crc->sched, + GNUNET_NO, + &run_continuation, + crc, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + return; + } + crc->phase++; + if (priority == get_priority (42)) + crc->uid = uid; +} + + +static void +check_update (void *cls, + const GNUNET_HashCode * key, + uint32_t size, + const void *data, + uint32_t type, + uint32_t priority, + uint32_t anonymity, + struct GNUNET_TIME_Absolute + expiration, uint64_t uid) +{ + struct CpsRunContext *crc = cls; + + if (key == NULL) + { + GNUNET_assert (crc->phase == RP_UPDATE_DONE); + crc->phase = RP_DONE; + GNUNET_SCHEDULER_add_continuation (crc->sched, + GNUNET_NO, + &run_continuation, + crc, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + return; + } + if ( (anonymity == get_anonymity (42)) && + (size == get_size (42)) && + (priority == get_priority (42) + 100) ) + { + crc->phase = RP_UPDATE_DONE; + } + else + GNUNET_assert (size == get_size (43)); +} + + static void run_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CpsRunContext *crc = cls; ok = (int) crc->phase; +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Test in phase %u\n", crc->phase); +#endif switch (crc->phase) { case RP_PUT: @@ -341,9 +438,79 @@ run_continuation (void *cls, crc, TIMEOUT); break; - /* check reservations */ - /* check update */ - /* test multiple results */ + case RP_RESERVE: + crc->phase = RP_PUT_MULTIPLE; + GNUNET_DATASTORE_reserve (datastore, + 128*1024, + 2, + &get_reserved, + crc, + TIMEOUT); + break; + case RP_PUT_MULTIPLE: + crc->phase = RP_PUT_MULTIPLE_NEXT; + GNUNET_DATASTORE_put (datastore, + crc->rid, + &crc->key, + get_size (42), + get_data (42), + get_type (42), + get_priority (42), + get_anonymity (42), + get_expiration (42), + TIMEOUT, + &check_success, + crc); + break; + case RP_PUT_MULTIPLE_NEXT: + crc->phase = RP_GET_MULTIPLE; + GNUNET_DATASTORE_put (datastore, + crc->rid, + &crc->key, + get_size (43), + get_data (43), + get_type (42), + get_priority (43), + get_anonymity (43), + get_expiration (43), + TIMEOUT, + &check_success, + crc); + break; + case RP_GET_MULTIPLE: + GNUNET_DATASTORE_get (datastore, + &crc->key, + get_type (42), + &check_multiple, + crc, + TIMEOUT); + break; + case RP_GET_MULTIPLE_NEXT: + case RP_GET_MULTIPLE_DONE: + GNUNET_assert (0); + break; + case RP_UPDATE: + GNUNET_assert (crc->uid > 0); + crc->phase = RP_UPDATE_VALIDATE; + GNUNET_DATASTORE_update (datastore, + crc->uid, + 100, + get_expiration (42), + &check_success, + crc, + TIMEOUT); + break; + case RP_UPDATE_VALIDATE: + GNUNET_DATASTORE_get (datastore, + &crc->key, + get_type (42), + &check_update, + crc, + TIMEOUT); + break; + case RP_UPDATE_DONE: + GNUNET_assert (0); + break; case RP_DONE: #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -368,7 +535,7 @@ run (void *cls, crc->sched = sched; crc->cfg = cfg; crc->phase = RP_PUT; - now.value = 1000000; + now = GNUNET_TIME_absolute_get (); datastore = GNUNET_DATASTORE_connect (cfg, sched); GNUNET_SCHEDULER_add_continuation (crc->sched, GNUNET_NO, diff --git a/src/datastore/test_datastore_api_management.c b/src/datastore/test_datastore_api_management.c new file mode 100644 index 000000000..f5dfa8a07 --- /dev/null +++ b/src/datastore/test_datastore_api_management.c @@ -0,0 +1,377 @@ +/* + This file is part of GNUnet. + (C) 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/* + * @file datastore/test_datastore_api_management.c + * @brief Test for the space management functions of the datastore implementation. + * @author Christian Grothoff + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_protocols.h" +#include "gnunet_datastore_service.h" + +#define VERBOSE GNUNET_NO + +/** + * How long until we give up on transmitting the message? + */ +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) + +/** + * Number of iterations to run; must be large enough + * so that the quota will be exceeded! + */ +#define ITERATIONS 5000 + +static struct GNUNET_DATASTORE_Handle *datastore; + +static struct GNUNET_TIME_Absolute now; + +static int ok; + + +static size_t +get_size (int i) +{ + return 8 + 8 * (i % 256); +} + + +static const void * +get_data (int i) +{ + static char buf[60000]; + memset (buf, i, 8 + 8 * (i % 256)); + return buf; +} + + +static int +get_type(int i) +{ + return 1; +} + + +static int +get_priority (int i) +{ + return i+1; +} + + +static int +get_anonymity(int i) +{ + return i; +} + + +static struct GNUNET_TIME_Absolute +get_expiration (int i) +{ + struct GNUNET_TIME_Absolute av; + + av.value = now.value + i * 1000; + return av; +} + +enum RunPhase + { + RP_DONE = 0, + RP_PUT, + RP_GET, + RP_GET_FAIL + }; + + +struct CpsRunContext +{ + GNUNET_HashCode key; + int i; + int found; + struct GNUNET_SCHEDULER_Handle *sched; + struct GNUNET_CONFIGURATION_Handle *cfg; + void *data; + size_t size; + enum RunPhase phase; +}; + + +static void +run_continuation (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + +static void +check_success (void *cls, + int success, + const char *msg) +{ + struct CpsRunContext *crc = cls; + if (GNUNET_OK != success) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "%s\n", msg); + GNUNET_assert (GNUNET_OK == success); + GNUNET_free_non_null (crc->data); + crc->data = NULL; + GNUNET_SCHEDULER_add_continuation (crc->sched, + GNUNET_NO, + &run_continuation, + crc, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); +} + + +static void +check_value (void *cls, + const GNUNET_HashCode * key, + uint32_t size, + const void *data, + uint32_t type, + uint32_t priority, + uint32_t anonymity, + struct GNUNET_TIME_Absolute + expiration, uint64_t uid) +{ + struct CpsRunContext *crc = cls; + int i; + + if (key == NULL) + { + crc->i--; + if (crc->found == GNUNET_YES) + { + crc->phase = RP_GET; + crc->found = GNUNET_NO; + } + else + { + fprintf (stderr, + "First not found was %u\n", crc->i); + crc->phase = RP_GET_FAIL; + } + if (0 == crc->i) + crc->phase = RP_DONE; + GNUNET_SCHEDULER_add_continuation (crc->sched, + GNUNET_NO, + &run_continuation, + crc, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + return; + } + i = crc->i; + crc->found = GNUNET_YES; + GNUNET_assert (size == get_size (i)); + GNUNET_assert (0 == memcmp (data, get_data(i), size)); + GNUNET_assert (type == get_type (i)); + GNUNET_assert (priority == get_priority (i)); + GNUNET_assert (anonymity == get_anonymity(i)); + GNUNET_assert (expiration.value == get_expiration(i).value); +} + + +static void +check_nothing (void *cls, + const GNUNET_HashCode * key, + uint32_t size, + const void *data, + uint32_t type, + uint32_t priority, + uint32_t anonymity, + struct GNUNET_TIME_Absolute + expiration, uint64_t uid) +{ + struct CpsRunContext *crc = cls; + GNUNET_assert (key == NULL); + if (crc->i == 0) + { + crc->phase = RP_DONE; + } + GNUNET_SCHEDULER_add_continuation (crc->sched, + GNUNET_NO, + &run_continuation, + crc, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); +} + + +static void +run_continuation (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct CpsRunContext *crc = cls; + ok = (int) crc->phase; + switch (crc->phase) + { + case RP_PUT: +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Executing `%s' number %u\n", + "PUT", + crc->i); +#endif + GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); + GNUNET_DATASTORE_put (datastore, + 0, + &crc->key, + get_size (crc->i), + get_data (crc->i), + get_type (crc->i), + get_priority (crc->i), + get_anonymity (crc->i), + get_expiration (crc->i), + TIMEOUT, + &check_success, + crc); + crc->i++; + if (crc->i == ITERATIONS) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Sleeping to give datastore time to clean up\n"); + sleep (5); + crc->phase = RP_GET; + crc->i--; + } + break; + case RP_GET: +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Executing `%s' number %u\n", + "GET", + crc->i); +#endif + GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); + GNUNET_DATASTORE_get (datastore, + &crc->key, + get_type (crc->i), + &check_value, + crc, + TIMEOUT); + break; + case RP_GET_FAIL: +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Executing `%s' number %u\n", + "GET", + crc->i); +#endif + GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); + GNUNET_DATASTORE_get (datastore, + &crc->key, + get_type (crc->i), + &check_nothing, + crc, + TIMEOUT); + break; + case RP_DONE: +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Finished, disconnecting\n"); +#endif + GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); + GNUNET_free (crc); + ok = 0; + } +} + + +static void +run (void *cls, + struct GNUNET_SCHEDULER_Handle *sched, + char *const *args, + const char *cfgfile, struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct CpsRunContext *crc; + + crc = GNUNET_malloc(sizeof(struct CpsRunContext)); + crc->sched = sched; + crc->cfg = cfg; + crc->phase = RP_PUT; + now = GNUNET_TIME_absolute_get (); + datastore = GNUNET_DATASTORE_connect (cfg, sched); + GNUNET_SCHEDULER_add_continuation (crc->sched, + GNUNET_NO, + &run_continuation, + crc, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + +} + + + +static int +check () +{ + pid_t pid; + char *const argv[] = { "test-datastore-api-management", + "-c", + "test_datastore_api_data.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + pid = GNUNET_OS_start_process ("gnunet-service-datastore", + "gnunet-service-datastore", +#if VERBOSE + "-L", "DEBUG", +#endif + "-c", "test_datastore_api_data.conf", NULL); + sleep (1); + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, + argv, "test-datastore-api", "nohelp", + options, &run, NULL); + if (0 != PLIBC_KILL (pid, SIGTERM)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + ok = 1; + } + GNUNET_OS_process_wait(pid); + if (ok != 0) + fprintf (stderr, "Missed some testcases: %u\n", ok); + return ok; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-datastore"); + GNUNET_log_setup ("test-datastore-api", +#if VERBOSE + "DEBUG", +#else + "WARNING", +#endif + NULL); + ret = check (); + + return ret; +} + + + +/* end of test_datastore_api_management.c */