diff --git a/tests/gpg/t-gpgconf.c b/tests/gpg/t-gpgconf.c index 1074eef3..d199d2eb 100644 --- a/tests/gpg/t-gpgconf.c +++ b/tests/gpg/t-gpgconf.c @@ -1,318 +1,366 @@ /* t-gpgconf.c - Regression test. Copyright (C) 2001, 2004, 2007 g10 Code GmbH This file is part of GPGME. GPGME is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. GPGME 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #ifdef HAVE_W32_SYSTEM #include #endif #include - -#define fail_if_err(err) \ - do \ - { \ - if (err) \ - { \ - fprintf (stderr, "%s:%d: %s: %s\n", \ - __FILE__, __LINE__, gpgme_strsource (err), \ - gpgme_strerror (err)); \ - exit (1); \ - } \ - } \ - while (0) - - -void -init_gpgme (gpgme_protocol_t proto) -{ - gpgme_error_t err; - - gpgme_check_version (NULL); - setlocale (LC_ALL, ""); - gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); -#ifndef HAVE_W32_SYSTEM - gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); -#endif - - err = gpgme_engine_check_version (proto); - fail_if_err (err); -} - +#include "t-support.h" static char * spaces (char *str, int extra) { static char buf[80]; int len = str ? strlen (str) : 0; int n; #define TABSTOP 30 n = TABSTOP - len - extra; memset (buf, ' ', sizeof (buf)); if (n < 1 || n > (sizeof (buf) - 1)) { buf[0] = '\n'; n = TABSTOP + 1; } buf[n] = '\0'; return buf; } void dump_arg (int type, gpgme_conf_arg_t arg) { if (!arg) { printf ("(none)"); return; } while (arg) { switch (type) { case GPGME_CONF_STRING: case GPGME_CONF_PATHNAME: case GPGME_CONF_LDAP_SERVER: case GPGME_CONF_KEY_FPR: case GPGME_CONF_PUB_KEY: case GPGME_CONF_SEC_KEY: case GPGME_CONF_ALIAS_LIST: printf ("`%s'", arg->value.string); break; case GPGME_CONF_UINT32: printf ("%u", arg->value.uint32); break; case GPGME_CONF_INT32: printf ("%i", arg->value.int32); break; case GPGME_CONF_NONE: printf ("%i (times)", arg->value.count); break; default: printf ("(unknown type)"); } arg = arg->next; if (arg) printf (" "); } } void dump_opt (gpgme_conf_opt_t opt) { char level; char runtime = (opt->flags & GPGME_CONF_RUNTIME) ? 'r' : ' '; switch (opt->level) { case GPGME_CONF_BASIC: level = 'b'; break; case GPGME_CONF_ADVANCED: level = 'a'; break; case GPGME_CONF_EXPERT: level = 'e'; break; case GPGME_CONF_INVISIBLE: level = 'i'; break; case GPGME_CONF_INTERNAL: level = '#'; break; default: level = '?'; } if (opt->flags & GPGME_CONF_GROUP) { printf ("\n"); printf ("%c%c [%s]%s%s\n", level, runtime, opt->name, spaces (opt->name, 5), opt->description ? opt->description : ""); } else { if (opt->argname) { const char *more = (opt->flags & GPGME_CONF_LIST) ? "..." : ""; if (opt->flags & GPGME_CONF_OPTIONAL) { printf ("%c%c --%s [%s%s] %s", level, runtime, opt->name, opt->argname, more, spaces (opt->name, 9 + strlen (opt->argname) + strlen (more))); } else { printf ("%c%c --%s %s%s %s", level, runtime, opt->name, opt->argname, more, spaces (opt->name, 7 + strlen (opt->argname) + strlen (more))); } } else printf ("%c%c --%s%s", level, runtime, opt->name, spaces (opt->name, 5)); if (opt->description) printf ("%s", opt->description); printf ("\n"); if (opt->flags & GPGME_CONF_DEFAULT) { printf ("%s%s = ", spaces (NULL, 0), opt->argname ? opt->argname : "(default)"); dump_arg (opt->type, opt->default_value); printf ("\n"); } else if (opt->flags & GPGME_CONF_DEFAULT_DESC) printf ("%s%s = %s\n", spaces (NULL, 0), opt->argname ? opt->argname : "(default)", opt->default_description); if (opt->no_arg_value) { printf ("%sNo Arg Def = ", spaces (NULL, 0)); dump_arg (opt->type, opt->no_arg_value); printf ("\n"); } if (opt->value) { printf ("%sCurrent = ", spaces (NULL, 0)); dump_arg (opt->type, opt->value); printf ("\n"); } } #if 0 arg = comp->options; while (opt) { dump_opt (opt); opt = opt->next; } #endif } void dump_comp (gpgme_conf_comp_t comp) { gpgme_conf_opt_t opt; printf ("COMPONENT\n"); printf ("=========\n"); printf (" Name: %s\n", comp->name); if (comp->description) printf (" Desc: %s\n", comp->description); if (comp->program_name) printf (" Path: %s\n", comp->program_name); printf ("\n"); opt = comp->options; while (opt) { dump_opt (opt); opt = opt->next; } } +int +lookup (gpgme_conf_comp_t conf, + const char *component, + const char *option, + gpgme_conf_comp_t *comp, + gpgme_conf_opt_t *opt) +{ + *comp = conf; + while (*comp && strcmp ((*comp)->name, component)) + *comp = (*comp)->next; + + if (*comp) + { + *opt = (*comp)->options; + while (*opt && strcmp ((*opt)->name, option)) + *opt = (*opt)->next; + + /* Allow for the option not to be there. */ + if (*opt) + return 1; /* Found. */ + } + + return 0; /* Not found. */ +} + +#include + + int main (void) { gpgme_ctx_t ctx; gpgme_error_t err; gpgme_conf_comp_t conf; gpgme_conf_comp_t comp; int first; + int i, N = 100; init_gpgme (GPGME_PROTOCOL_GPGCONF); err = gpgme_new (&ctx); fail_if_err (err); err = gpgme_op_conf_load (ctx, &conf); fail_if_err (err); comp = conf; first = 1; while (comp) { if (!first) printf ("\n"); else first = 0; dump_comp (comp); comp = comp->next; } -#if 1 /* Now change something. */ - { - unsigned int count = 1; + fprintf (stderr, " dirmngr.verbose "); + for (i = 0; i < N; i++) { + unsigned int count = i % 4 + 1; /* counts must not be zero */ gpgme_conf_arg_t arg; gpgme_conf_opt_t opt; err = gpgme_conf_arg_new (&arg, GPGME_CONF_NONE, &count); fail_if_err (err); - comp = conf; - while (comp && strcmp (comp->name, "dirmngr")) - comp = comp->next; + if (lookup (conf, "dirmngr", "verbose", &comp, &opt)) + { + /* Found. */ + err = gpgme_conf_opt_change (opt, 0, arg); + fail_if_err (err); - if (comp) + err = gpgme_op_conf_save (ctx, comp); + fail_if_err (err); + } + else { - opt = comp->options; - while (opt && strcmp (opt->name, "verbose")) - opt = opt->next; - - /* Allow for the verbose option not to be there. */ - if (opt) - { - err = gpgme_conf_opt_change (opt, 0, arg); - fail_if_err (err); - - err = gpgme_op_conf_save (ctx, comp); - fail_if_err (err); - } + fprintf (stderr, "Skipping test, option dirmngr.verbose not found.\n"); + break; } + + /* Reload config and verify that the value was updated. */ + gpgme_conf_release (conf); + err = gpgme_op_conf_load (ctx, &conf); + fail_if_err (err); + if (lookup (conf, "dirmngr", "verbose", &comp, &opt)) + { + /* Found. */ + test (opt->alt_type == GPGME_CONF_NONE); + test ((unsigned long) opt->value->value.count == count); + } + + fprintf (stderr, "."); + fflush (stderr); } -#endif - gpgme_conf_release (conf); + /* Now change something else. */ + fprintf (stderr, " gpg.keyserver "); + for (i = 0; i < N; i++) { + const char *values[2] = { "hkp://foo.bar", "hkps://bar.foo" }; + gpgme_conf_arg_t arg; + gpgme_conf_opt_t opt; + err = gpgme_conf_arg_new (&arg, GPGME_CONF_STRING, values[i%2]); + fail_if_err (err); + + if (lookup (conf, "gpg", "keyserver", &comp, &opt)) + { + /* Found. */ + test (opt->alt_type == GPGME_CONF_STRING); + err = gpgme_conf_opt_change (opt, 0, arg); + fail_if_err (err); + + err = gpgme_op_conf_save (ctx, comp); + fail_if_err (err); + } + else + { + fprintf (stderr, "Skipping test, option gpg.keyserver not found.\n"); + break; + } + + /* Reload config and verify that the value was updated. */ + gpgme_conf_release (conf); + err = gpgme_op_conf_load (ctx, &conf); + fail_if_err (err); + if (lookup (conf, "gpg", "keyserver", &comp, &opt)) + { + /* Found. */ + test (opt->alt_type == GPGME_CONF_STRING); + test (strcmp (opt->value->value.string, values[i%2]) == 0); + } + + fprintf (stderr, "."); + fflush (stderr); + } + fprintf (stderr, "\n"); + + gpgme_conf_release (conf); + gpgme_release (ctx); return 0; } diff --git a/tests/gpg/t-support.h b/tests/gpg/t-support.h index db69dd0e..f6dec682 100644 --- a/tests/gpg/t-support.h +++ b/tests/gpg/t-support.h @@ -1,187 +1,215 @@ /* t-support.h - Helper routines for regression tests. Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH This file is part of GPGME. GPGME is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. GPGME 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #ifdef HAVE_W32_SYSTEM #include #endif #include #ifndef DIM #define DIM(v) (sizeof(v)/sizeof((v)[0])) #endif #define fail_if_err(err) \ do \ { \ if (err) \ { \ fprintf (stderr, "%s:%d: %s: %s\n", \ __FILE__, __LINE__, gpgme_strsource (err), \ gpgme_strerror (err)); \ exit (1); \ } \ } \ while (0) +#ifdef GPGRT_HAVE_MACRO_FUNCTION +void GPGRT_ATTR_NORETURN +_test (const char *expr, const char *file, int line, + const char *func) +{ + fprintf (stderr, "Test \"%s\" in %s failed (%s:%d)\n", + expr, func, file, line); + exit (1); +} +# define test(expr) \ + ((expr) \ + ? (void) 0 \ + : _test (#expr, __FILE__, __LINE__, __FUNCTION__)) +#else /*!GPGRT_HAVE_MACRO_FUNCTION*/ +void +_test (const char *expr, const char *file, int line) +{ + fprintf (stderr, "Test \"%s\" failed (%s:%d)\n", + expr, file, line); + exit (1); +} +# define test(expr) \ + ((expr) \ + ? (void) 0 \ + : _test (#expr, __FILE__, __LINE__)) +#endif /*!GPGRT_HAVE_MACRO_FUNCTION*/ + + static const char * nonnull (const char *s) { return s? s :"[none]"; } void print_data (gpgme_data_t dh) { #define BUF_SIZE 512 char buf[BUF_SIZE + 1]; int ret; ret = gpgme_data_seek (dh, 0, SEEK_SET); if (ret) fail_if_err (gpgme_err_code_from_errno (errno)); while ((ret = gpgme_data_read (dh, buf, BUF_SIZE)) > 0) fwrite (buf, ret, 1, stdout); if (ret < 0) fail_if_err (gpgme_err_code_from_errno (errno)); } gpgme_error_t passphrase_cb (void *opaque, const char *uid_hint, const char *passphrase_info, int last_was_bad, int fd) { int res; char pass[] = "abc\n"; int passlen = strlen (pass); int off = 0; (void)opaque; (void)uid_hint; (void)passphrase_info; (void)last_was_bad; do { res = gpgme_io_write (fd, &pass[off], passlen - off); if (res > 0) off += res; } while (res > 0 && off != passlen); return off == passlen ? 0 : gpgme_error_from_errno (errno); } char * make_filename (const char *fname) { const char *srcdir = getenv ("srcdir"); char *buf; if (!srcdir) srcdir = "."; buf = malloc (strlen(srcdir) + strlen(fname) + 2); if (!buf) exit (8); strcpy (buf, srcdir); strcat (buf, "/"); strcat (buf, fname); return buf; } void init_gpgme (gpgme_protocol_t proto) { gpgme_error_t err; gpgme_check_version (NULL); setlocale (LC_ALL, ""); gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); #ifndef HAVE_W32_SYSTEM gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); #endif err = gpgme_engine_check_version (proto); fail_if_err (err); } void print_import_result (gpgme_import_result_t r) { gpgme_import_status_t st; for (st=r->imports; st; st = st->next) { printf (" fpr: %s err: %d (%s) status:", nonnull (st->fpr), st->result, gpgme_strerror (st->result)); if (st->status & GPGME_IMPORT_NEW) fputs (" new", stdout); if (st->status & GPGME_IMPORT_UID) fputs (" uid", stdout); if (st->status & GPGME_IMPORT_SIG) fputs (" sig", stdout); if (st->status & GPGME_IMPORT_SUBKEY) fputs (" subkey", stdout); if (st->status & GPGME_IMPORT_SECRET) fputs (" secret", stdout); putchar ('\n'); } printf ("key import summary:\n" " considered: %d\n" " no user id: %d\n" " imported: %d\n" " imported_rsa: %d\n" " unchanged: %d\n" " new user ids: %d\n" " new subkeys: %d\n" " new signatures: %d\n" " new revocations: %d\n" " secret read: %d\n" " secret imported: %d\n" " secret unchanged: %d\n" " skipped new keys: %d\n" " not imported: %d\n", r->considered, r->no_user_id, r->imported, r->imported_rsa, r->unchanged, r->new_user_ids, r->new_sub_keys, r->new_signatures, r->new_revocations, r->secret_read, r->secret_imported, r->secret_unchanged, r->skipped_new_keys, r->not_imported); }