gpgme: prerequisite for running tests under gpgme/tests/gpg

Seiya Kawashima skawashima at uchicago.edu
Wed Jun 8 19:12:45 CEST 2016


Hi,

I've been learning how GPGME-1.6.0,  GnuPG stable-2.0.30 and Pinentry-0.9.7 work downloading, modifying and compiling them. As long as I know,  gpgme/tests/gpg/t-decrypt.c, gpgme/tests/gpg/t-decrypt-verify.c, gpgme/tests/gpg/t-encrypt.c, gpgme/tests/gpg/t-encrypt-large.c and t-encrypt-sign.c don't run simply compiling. I've checked the source code in GPGME-1.6.0 and via git as of 06/08/2016. All the tests seem to stay the same so I assume that they still don't run. If I totally miss the point, please disregard the email. I would need more study on them.

The errors returned by the tests are such as t-encrypt.c:60: GPGME: End of file and t-decrypt.c:65: GPGME: Decryption failed.

These tests seem to assume that specific keys exist. I'm not sure about this but they might also expect some environment variables as in the discussion at http://marc.info/?l=gnupg-devel&m=120346698810871&w=2 like below.
> The included test suite comes with its own environment, which is
> provided by environment variables.  Try something like:
>
> GNUPGHOME=`pwd` srcdir=`pwd` ./t-encrypt

However, I think that it might be better that the tests run simply compiling.

To make them run without the assumptions, It might be better to have the work flow of generate key, encrypt or decrypt and delete the generated key on each test. With this way, they can run simply compiling. To make this happen, enough entropy should be provided so that the tests don't hang when generating keys. I would like to show you my approach for gpgme/tests/gpg/t-decrypt.c as follows:

commit 55e5f8ae371b8cf1207b1b1ec077d9518757f057
Author: Seiya Kawashima <skawashima at uchicago.edu>
Date:   Wed Jun 8 04:56:06 2016 -0500

    add work flow of generate key, encrypt, decrypt and delete key in tests/gpg/t-decrypt.c

diff --git a/tests/gpg/t-decrypt.c b/tests/gpg/t-decrypt.c
index 2a2f4d7..60a39b3 100644
--- a/tests/gpg/t-decrypt.c
+++ b/tests/gpg/t-decrypt.c
@@ -41,37 +41,79 @@ main (int argc, char *argv[])
 {
   gpgme_ctx_t ctx;
   gpgme_error_t err;
-  gpgme_data_t in, out;
-  gpgme_decrypt_result_t result;
-  const char *cipher_1_asc = make_filename ("cipher-1.asc");
+  gpgme_data_t in,out;
+  gpgme_genkey_result_t gen_result;
+  gpgme_encrypt_result_t enc_result;
+  gpgme_decrypt_result_t dec_result;
+  gpgme_key_t keys[2] = {NULL,NULL};
+
   char *agent_info;
+  agent_info = getenv("GPG_AGENT_INFO");
+  if (!(agent_info && strchr (agent_info, ':')))
+    gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
 
   init_gpgme (GPGME_PROTOCOL_OpenPGP);
 
   err = gpgme_new (&ctx);
   fail_if_err (err);
+  gpgme_set_armor (ctx,1);
 
-  agent_info = getenv("GPG_AGENT_INFO");
-  if (!(agent_info && strchr (agent_info, ':')))
-    gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
+
+  /* Generate test key for encryption. */
+  err = generate_test_key (ctx,NULL);
+  fail_if_err (err);
+  gen_result = gpgme_op_genkey_result (ctx);
 
-  err = gpgme_data_new_from_file (&in, cipher_1_asc, 1);
+  /* Search key for encryption. */
+  gpgme_key_t key;
+  err = gpgme_get_key (ctx,gen_result->fpr,&key,1);
   fail_if_err (err);
 
+  /* Initialize input buffer. */
+  err = gpgme_data_new_from_mem (&in,"Hallo Leute\n", 12, 0);
+  fail_if_err (err);
+
+  /* Initialize output buffer. */
   err = gpgme_data_new (&out);
   fail_if_err (err);
-  
-  err = gpgme_op_decrypt (ctx, in, out);
+
+  /* Encrypt data. */
+  keys[0] = key;
+  err = gpgme_op_encrypt (ctx,keys,GPGME_ENCRYPT_ALWAYS_TRUST,in,out);
   fail_if_err (err);
-  result = gpgme_op_decrypt_result (ctx);
-  if (result->unsupported_algorithm)
+  enc_result = gpgme_op_encrypt_result (ctx);
+  if (enc_result->invalid_recipients)
     {
-      fprintf (stderr, "%s:%i: unsupported algorithm: %s\n",
-	       __FILE__, __LINE__, result->unsupported_algorithm);
+      fprintf (stderr, "Invalid recipient encountered: %s\n",
+	       enc_result->invalid_recipients->fpr);
       exit (1);
     }
   print_data (out);
-   
+
+  /* out stores encrypted data and it's the input for decryption. Use in as
+     the output for decryption. */
+  gpgme_data_release (in);
+  err = gpgme_data_new (&in);
+  fail_if_err (err);
+
+  /* Decrypt data. */
+  err = gpgme_op_decrypt (ctx,out,in);
+  fail_if_err (err);
+  dec_result = gpgme_op_decrypt_result (ctx);
+  if (dec_result->unsupported_algorithm)
+    {
+      fprintf (stderr, "%s:%i: unsupported algorithm: %s\n",
+	       __FILE__, __LINE__, dec_result->unsupported_algorithm);
+      exit (1);
+    }
+  print_data (in);
+
+  err = delete_test_key (ctx,key);
+  fail_if_err (err);
+
   gpgme_data_release (in);
   gpgme_data_release (out);
   gpgme_release (ctx);
diff --git a/tests/gpg/t-support.h b/tests/gpg/t-support.h
index 6a18b5c..c541a07 100644
--- a/tests/gpg/t-support.h
+++ b/tests/gpg/t-support.h
@@ -69,6 +69,13 @@ print_data (gpgme_data_t dh)
     fwrite (buf, ret, 1, stdout);
   if (ret < 0)
     fail_if_err (gpgme_err_code_from_errno (errno));
+
+  /* Reset read position to the beginning so that dh can be used as input
+     for another operation after this method call. For example, dh is an
+     output from encryption and also is used as an input for decryption.
+     Otherwise GPG_ERR_NO_DATA is returned since this method moves the
+     read position. */
+  ret = gpgme_data_seek (dh, 0, SEEK_SET);
 }
 
 
@@ -187,3 +194,32 @@ print_import_result (gpgme_import_result_t r)
           r->not_imported);
 }
 
+gpgme_error_t
+generate_test_key (gpgme_ctx_t ctx,
+  void (*progress_meter) (void *hook, const char *what, int type, int current,
+                          int total))
+{
+  gpgme_error_t err;
+  const char *parms = "<GnupgKeyParms format=\"internal\">\n"
+    "Key-Type: DSA\n"
+    "Key-Length: 1024\n"
+    "Subkey-Type: ELG-E\n"
+    "Subkey-Length: 1024\n"
+    "Name-Real: Joe Tester\n"
+    "Name-Comment: with stupid passphrase\n"
+    "Name-Email: joe at foo.bar\n"
+    "Expire-Date: 0\n"
+    "Passphrase: abc\n"
+    "</GnupgKeyParms>\n";
+
+  gpgme_set_progress_cb (ctx, progress_meter, NULL);
+  return gpgme_op_genkey (ctx, parms, NULL, NULL);
+}
+
+gpgme_error_t
+delete_test_key (gpgme_ctx_t ctx,gpgme_key_t key)
+{
+  gpgme_error_t err = gpgme_op_delete (ctx,key,1);
+  gpgme_key_unref (key);
+  return err;
+}

Thank you
Seiya



More information about the Gnupg-devel mailing list