From ee7ec1256b24dc340656c331ef92fc59cad817b6 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 2 Sep 2015 15:07:06 +0200 Subject: [PATCH] g10: Add test for keydb as well as new testing infrastructure. * g10/Makefile.am (EXTRA_DIST): Add test.c. (AM_CPPFLAGS): Add -DSOURCE_DIR="\"$(srcdir)\"". (module_tests): Add t-keydb. (t_keydb_SOURCES): New variable. (t_keydb_LDADD): Likewise. * g10/t-keydb.c: New file. * g10/t-keydb-keyring.kbx: New file. * g10/test-stubs.c: New file. * g10/test.c: New file. -- Signed-off-by: Neal H. Walfield . --- g10/Makefile.am | 9 +- g10/t-keydb-keyring.kbx | Bin 0 -> 5104 bytes g10/t-keydb.c | 87 +++++++++ g10/test-stubs.c | 413 ++++++++++++++++++++++++++++++++++++++++ g10/test.c | 141 ++++++++++++++ 5 files changed, 647 insertions(+), 3 deletions(-) create mode 100644 g10/t-keydb-keyring.kbx create mode 100644 g10/t-keydb.c create mode 100644 g10/test-stubs.c create mode 100644 g10/test.c diff --git a/g10/Makefile.am b/g10/Makefile.am index 0c53eab97..421870c5e 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -19,9 +19,9 @@ ## Process this file with automake to produce Makefile.in EXTRA_DIST = options.skel distsigkey.gpg ChangeLog-2011 gpg-w32info.rc \ - gpg.w32-manifest.in + gpg.w32-manifest.in test.c -AM_CPPFLAGS = -I$(top_srcdir)/common +AM_CPPFLAGS = -I$(top_srcdir)/common -DSOURCE_DIR="\"$(srcdir)\"" include $(top_srcdir)/am/cmacros.am @@ -150,9 +150,12 @@ gpgv2_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \ gpgv2_LDFLAGS = $(extra_bin_ldflags) t_common_ldadd = -module_tests = t-rmd160 +module_tests = t-rmd160 t-keydb t_rmd160_SOURCES = t-rmd160.c rmd160.c t_rmd160_LDADD = $(t_common_ldadd) +t_keydb_SOURCES = t-keydb.c test-stubs.c $(common_source) +t_keydb_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \ + $(LIBICONV) $(t_common_ldadd) $(PROGRAMS): $(needed_libs) ../common/libgpgrl.a diff --git a/g10/t-keydb-keyring.kbx b/g10/t-keydb-keyring.kbx new file mode 100644 index 0000000000000000000000000000000000000000..a1d3af073a3648309b8e9080b881bc3446d0c601 GIT binary patch literal 5104 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. + */ + +#include "test.c" + +#include "keydb.h" + +static void +do_test (int argc, char *argv[]) +{ + int rc; + KEYDB_HANDLE hd1, hd2; + KEYDB_SEARCH_DESC desc1, desc2; + KBNODE kb1, kb2; + char *uid1; + char *uid2; + + (void) argc; + (void) argv; + + rc = keydb_add_resource (SOURCE_DIR "/t-keydb-keyring.kbx", 0); + if (rc) + ABORT ("Failed to open keyring."); + + hd1 = keydb_new (); + hd2 = keydb_new (); + + rc = classify_user_id ("2689 5E25 E844 6D44 A26D 8FAF 2F79 98F3 DBFC 6AD9", + &desc1, 0); + if (rc) + ABORT ("Failed to convert fingerprint for DBFC6AD9"); + + rc = keydb_search (hd1, &desc1, 1, NULL); + if (rc) + ABORT ("Failed to lookup key associated with DBFC6AD9"); + + + classify_user_id ("8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367", + &desc2, 0); + if (rc) + ABORT ("Failed to convert fingerprint for 1E42B367"); + + rc = keydb_search (hd2, &desc2, 1, NULL); + if (rc) + ABORT ("Failed to lookup key associated with 1E42B367"); + + rc = keydb_get_keyblock (hd2, &kb2); + if (rc) + ABORT ("Failed to get keyblock for 1E42B367"); + + rc = keydb_get_keyblock (hd1, &kb1); + if (rc) + ABORT ("Failed to get keyblock for DBFC6AD9"); + + while (kb1 && kb1->pkt->pkttype != PKT_USER_ID) + kb1 = kb1->next; + if (! kb1) + ABORT ("DBFC6AD9 has no user id packet"); + uid1 = kb1->pkt->pkt.user_id->name; + + while (kb2 && kb2->pkt->pkttype != PKT_USER_ID) + kb2 = kb2->next; + if (! kb2) + ABORT ("1E42B367 has no user id packet"); + uid2 = kb2->pkt->pkt.user_id->name; + + printf ("user id for DBFC6AD9: %s\n", uid1); + printf ("user id for 1E42B367: %s\n", uid2); + + TEST_P ("cache consistency", strcmp (uid1, uid2) != 0); +} diff --git a/g10/test-stubs.c b/g10/test-stubs.c new file mode 100644 index 000000000..c6f6d68e9 --- /dev/null +++ b/g10/test-stubs.c @@ -0,0 +1,413 @@ +/* test-stubs.c - The GnuPG signature verify utility + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006, + * 2008, 2009, 2012 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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 3 of the License, or + * (at your option) any later version. + * + * GnuPG 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 this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define INCLUDED_BY_MAIN_MODULE 1 +#include "gpg.h" +#include "util.h" +#include "packet.h" +#include "iobuf.h" +#include "main.h" +#include "options.h" +#include "keydb.h" +#include "trustdb.h" +#include "filter.h" +#include "ttyio.h" +#include "i18n.h" +#include "sysutils.h" +#include "status.h" +#include "call-agent.h" + +int g10_errors_seen; + + +void +g10_exit( int rc ) +{ + rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0; + exit(rc ); +} + + +/* Stub: + * We have to override the trustcheck from pkclist.c becuase + * this utility assumes that all keys in the keyring are trustworthy + */ +int +check_signatures_trust( PKT_signature *sig ) +{ + (void)sig; + return 0; +} + +void +read_trust_options(byte *trust_model, ulong *created, ulong *nextcheck, + byte *marginals, byte *completes, byte *cert_depth, + byte *min_cert_level) +{ + (void)trust_model; + (void)created; + (void)nextcheck; + (void)marginals; + (void)completes; + (void)cert_depth; + (void)min_cert_level; +} + +/* Stub: + * We don't have the trustdb , so we have to provide some stub functions + * instead + */ + +int +cache_disabled_value(PKT_public_key *pk) +{ + (void)pk; + return 0; +} + +void +check_trustdb_stale(void) +{ +} + +int +get_validity_info (PKT_public_key *pk, PKT_user_id *uid) +{ + (void)pk; + (void)uid; + return '?'; +} + +unsigned int +get_validity (PKT_public_key *pk, PKT_user_id *uid) +{ + (void)pk; + (void)uid; + return 0; +} + +const char * +trust_value_to_string (unsigned int value) +{ + (void)value; + return "err"; +} + +const char * +uid_trust_string_fixed (PKT_public_key *key, PKT_user_id *uid) +{ + (void)key; + (void)uid; + return "err"; +} + +int +get_ownertrust_info (PKT_public_key *pk) +{ + (void)pk; + return '?'; +} + +unsigned int +get_ownertrust (PKT_public_key *pk) +{ + (void)pk; + return TRUST_UNKNOWN; +} + + +/* Stubs: + * Because we only work with trusted keys, it does not make sense to + * get them from a keyserver + */ + +struct keyserver_spec * +keyserver_match (struct keyserver_spec *spec) +{ + (void)spec; + return NULL; +} + +int +keyserver_import_keyid (u32 *keyid, void *dummy) +{ + (void)keyid; + (void)dummy; + return -1; +} + +int +keyserver_import_cert (const char *name) +{ + (void)name; + return -1; +} + +int +keyserver_import_pka (const char *name,unsigned char *fpr) +{ + (void)name; + (void)fpr; + return -1; +} + +int +keyserver_import_name (const char *name,struct keyserver_spec *spec) +{ + (void)name; + (void)spec; + return -1; +} + +int +keyserver_import_ldap (const char *name) +{ + (void)name; + return -1; +} + +/* Stub: + * No encryption here but mainproc links to these functions. + */ +gpg_error_t +get_session_key (PKT_pubkey_enc *k, DEK *dek) +{ + (void)k; + (void)dek; + return GPG_ERR_GENERAL; +} + +/* Stub: */ +gpg_error_t +get_override_session_key (DEK *dek, const char *string) +{ + (void)dek; + (void)string; + return GPG_ERR_GENERAL; +} + +/* Stub: */ +int +decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) +{ + (void)ctrl; + (void)procctx; + (void)ed; + (void)dek; + return GPG_ERR_GENERAL; +} + + +/* Stub: + * No interactive commands, so we don't need the helptexts + */ +void +display_online_help (const char *keyword) +{ + (void)keyword; +} + +/* Stub: + * We don't use secret keys, but getkey.c links to this + */ +int +check_secret_key (PKT_public_key *pk, int n) +{ + (void)pk; + (void)n; + return GPG_ERR_GENERAL; +} + +/* Stub: + * No secret key, so no passphrase needed + */ +DEK * +passphrase_to_dek (u32 *keyid, int pubkey_algo, + int cipher_algo, STRING2KEY *s2k, int mode, + const char *tmp, int *canceled) +{ + (void)keyid; + (void)pubkey_algo; + (void)cipher_algo; + (void)s2k; + (void)mode; + (void)tmp; + + if (canceled) + *canceled = 0; + return NULL; +} + +void +passphrase_clear_cache (u32 *keyid, const char *cacheid, int algo) +{ + (void)keyid; + (void)cacheid; + (void)algo; +} + +struct keyserver_spec * +parse_preferred_keyserver(PKT_signature *sig) +{ + (void)sig; + return NULL; +} + +struct keyserver_spec * +parse_keyserver_uri (const char *uri, int require_scheme, + const char *configname, unsigned int configlineno) +{ + (void)uri; + (void)require_scheme; + (void)configname; + (void)configlineno; + return NULL; +} + +void +free_keyserver_spec (struct keyserver_spec *keyserver) +{ + (void)keyserver; +} + +/* Stubs to avoid linking to photoid.c */ +void +show_photos (const struct user_attribute *attrs, int count, PKT_public_key *pk) +{ + (void)attrs; + (void)count; + (void)pk; +} + +int +parse_image_header (const struct user_attribute *attr, byte *type, u32 *len) +{ + (void)attr; + (void)type; + (void)len; + return 0; +} + +char * +image_type_to_string (byte type, int string) +{ + (void)type; + (void)string; + return NULL; +} + +#ifdef ENABLE_CARD_SUPPORT +int +agent_scd_getattr (const char *name, struct agent_card_info_s *info) +{ + (void)name; + (void)info; + return 0; +} +#endif /* ENABLE_CARD_SUPPORT */ + +/* We do not do any locking, so use these stubs here */ +void +dotlock_disable (void) +{ +} + +dotlock_t +dotlock_create (const char *file_to_lock, unsigned int flags) +{ + (void)file_to_lock; + (void)flags; + return NULL; +} + +void +dotlock_destroy (dotlock_t h) +{ + (void)h; +} + +int +dotlock_take (dotlock_t h, long timeout) +{ + (void)h; + (void)timeout; + return 0; +} + +int +dotlock_release (dotlock_t h) +{ + (void)h; + return 0; +} + +void +dotlock_remove_lockfiles (void) +{ +} + +gpg_error_t +agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk) +{ + (void)ctrl; + (void)pk; + return gpg_error (GPG_ERR_NO_SECKEY); +} + +gpg_error_t +agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) +{ + (void)ctrl; + (void)keyblock; + return gpg_error (GPG_ERR_NO_SECKEY); +} + +gpg_error_t +agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno) +{ + (void)ctrl; + (void)hexkeygrip; + *r_serialno = NULL; + return gpg_error (GPG_ERR_NO_SECKEY); +} + +gpg_error_t +gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid, + unsigned char **r_fpr, size_t *r_fprlen, + char **r_url) +{ + (void)ctrl; + (void)userid; + if (r_fpr) + *r_fpr = NULL; + if (r_fprlen) + *r_fprlen = 0; + if (r_url) + *r_url = NULL; + return gpg_error (GPG_ERR_NOT_FOUND); +} diff --git a/g10/test.c b/g10/test.c new file mode 100644 index 000000000..6910f95ad --- /dev/null +++ b/g10/test.c @@ -0,0 +1,141 @@ +/* test.c - Infrastructure for unit tests. + * Copyright (C) 2015 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG 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 3 of the License, or + * (at your option) any later version. + * + * GnuPG 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 this program; if not, see . + */ + +#include +#include "gpg.h" + +/* A unit test consists of one or more tests. Tests can be broken + into groups and each group can consist of one or more tests. */ + +/* The number of test groups. */ +static int test_groups; +/* The current test group. */ +static char *test_group; + +/* Whether there was already a failure in the current test group. */ +static int current_test_group_failed; +/* The number of test groups with a failure. */ +static int test_groups_failed; + +/* The total number of tests. */ +static int tests; +/* The total number of tests that failed. */ +static int tests_failed; + +#define TEST_GROUP(description) \ + do { \ + test_group = (description); \ + test_groups ++; \ + current_test_group_failed = 0; \ + } while (0) + +#define STRINGIFY2(x) #x +#define STRINGIFY(x) STRINGIFY2(x) + +/* Execute a test. */ +#define TEST(description, test, expected) \ + do { \ + int test_result; \ + int expected_result; \ + \ + tests ++; \ + \ + printf ("%d. Checking %s...", \ + tests, (description) ?: ""); \ + fflush (stdout); \ + \ + test_result = (test); \ + expected_result = (expected); \ + \ + if (test_result == expected_result) \ + { \ + printf (" ok.\n"); \ + } \ + else \ + { \ + printf (" failed.\n"); \ + printf (" %s == %s failed.\n", \ + STRINGIFY(test), \ + STRINGIFY(expected)); \ + tests_failed ++; \ + if (! current_test_group_failed) \ + { \ + current_test_group_failed = 1; \ + test_groups_failed ++; \ + } \ + } \ + } while (0) + +/* Test that a condition evaluates to true. */ +#define TEST_P(description, test) \ + TEST(description, !!(test), 1) + +/* Like CHECK, but if the test fails, abort the program. */ +#define ASSERT(description, test, expected) \ + do { \ + int tests_failed_pre = tests_failed; \ + CHECK(description, test, expected); \ + if (tests_failed_pre != tests_failed) \ + exit (1); \ + } while (0) + +/* Call this if something went wrong. */ +#define ABORT(message) \ + do { \ + printf ("aborting..."); \ + if (message) \ + printf (" %s\n", (message)); \ + \ + exit(1); \ + } while (0) + +/* You need to fill this function in. */ +static void do_test (int argc, char *argv[]); + +static void +print_results (void) +{ + if (tests_failed == 0) + { + printf ("All %d tests passed.\n", tests); + exit (0); + } + else + { + printf ("%d of %d tests failed", + tests_failed, tests); + if (test_groups > 1) + printf (" (%d of %d groups)", + test_groups_failed, test_groups); + printf ("\n"); + + exit (1); + } +} + +int +main (int argc, char *argv[]) +{ + (void) test_group; + + do_test (argc, argv); + atexit (print_results); + + return tests_failed == 0; +}