[gnome-keyring: 2/3] gcr: Review changes for GcrGnupgProcess from Phillip Withnall



commit e2ca61d312291a71075a1c30d7dbb3826ce0d16d
Author: Stef Walter <stefw collabora co uk>
Date:   Tue Jul 12 12:47:39 2011 +0200

    gcr: Review changes for GcrGnupgProcess from Phillip Withnall
    
     * Better docs
     * Disconnect signal handlers properly.
     * Cleanup tests.
     * Other bits

 gcr/gcr-gnupg-collection.c                         |   26 +++--
 gcr/gcr-gnupg-process.c                            |   85 ++++++++++++---
 gcr/gcr-gnupg-process.h                            |    3 +-
 .../files/gnupg-mock/mock-status-and-attribute     |    2 +-
 gcr/tests/test-gnupg-process.c                     |  117 +++++++++++++++++---
 5 files changed, 193 insertions(+), 40 deletions(-)
---
diff --git a/gcr/gcr-gnupg-collection.c b/gcr/gcr-gnupg-collection.c
index 44abe93..1fc2e21 100644
--- a/gcr/gcr-gnupg-collection.c
+++ b/gcr/gcr-gnupg-collection.c
@@ -140,6 +140,12 @@ _gcr_gnupg_collection_class_init (GcrGnupgCollectionClass *klass)
 	gobject_class->dispose = _gcr_gnupg_collection_dispose;
 	gobject_class->finalize = _gcr_gnupg_collection_finalize;
 
+	/**
+	 * GcrGnupgCollection:directory:
+	 *
+	 * Directory to load the gnupg keys from, or %NULL for default
+	 * ~/.gnupg/ directory.
+	 */
 	g_object_class_install_property (gobject_class, PROP_DIRECTORY,
 	           g_param_spec_string ("directory", "Directory", "Gnupg Directory",
 	                                NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -239,16 +245,18 @@ _gcr_gnupg_collection_load_free (gpointer data)
 	g_hash_table_destroy (load->difference);
 	g_object_unref (load->collection);
 
-	if (load->process)
+	if (load->process) {
+		if (load->output_sig)
+			g_signal_handler_disconnect (load->process, load->output_sig);
+		if (load->error_sig)
+			g_signal_handler_disconnect (load->process, load->error_sig);
+		if (load->status_sig)
+			g_signal_handler_disconnect (load->process, load->status_sig);
+		if (load->attribute_sig)
+			g_signal_handler_disconnect (load->process, load->attribute_sig);
 		g_object_unref (load->process);
-	if (load->output_sig)
-		g_source_remove (load->output_sig);
-	if (load->error_sig)
-		g_source_remove (load->error_sig);
-	if (load->status_sig)
-		g_source_remove (load->status_sig);
-	if (load->attribute_sig)
-		g_source_remove (load->attribute_sig);
+	}
+
 	if (load->cancel)
 		g_object_unref (load->cancel);
 	g_slice_free (GcrGnupgCollectionLoad, load);
diff --git a/gcr/gcr-gnupg-process.c b/gcr/gcr-gnupg-process.c
index e1c7a00..b4a4637 100644
--- a/gcr/gcr-gnupg-process.c
+++ b/gcr/gcr-gnupg-process.c
@@ -29,13 +29,23 @@
 #include "gcr-marshal.h"
 #include "gcr-util.h"
 
-#include "egg/egg-spawn.h"
+#include <glib/gi18n-lib.h>
 
 #include <sys/wait.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 
+/**
+ * GcrGnupgProcessFlags:
+ * @GCR_GNUPG_PROCESS_NONE: No flags
+ * @GCR_GNUPG_PROCESS_RESPECT_LOCALE: Respect the user's locale when running gnupg.
+ * @GCR_GNUPG_PROCESS_WITH_STATUS: Ask the process to send status records.
+ * @GCR_GNUPG_PROCESS_WITH_ATTRIBUTES: Ask the process to output attribute data.
+ *
+ * Flags for running a gnupg process.
+ */
+
 enum {
 	PROP_0,
 	PROP_DIRECTORY,
@@ -73,6 +83,7 @@ typedef struct _GnupgSource {
 	GPid child_pid;
 	guint child_sig;
 
+	GCancellable *cancellable;
 	guint cancel_sig;
 } GnupgSource;
 
@@ -178,29 +189,68 @@ _gcr_gnupg_process_class_init (GcrGnupgProcessClass *klass)
 	gobject_class->set_property = _gcr_gnupg_process_set_property;
 	gobject_class->finalize = _gcr_gnupg_process_finalize;
 
+	/**
+	 * GcrGnupgProcess:directory:
+	 *
+	 * Directory to run as gnupg home directory, or %NULL for default
+	 * ~/.gnupg/ directory.
+	 */
 	g_object_class_install_property (gobject_class, PROP_DIRECTORY,
 	           g_param_spec_string ("directory", "Directory", "Gnupg Directory",
 	                                NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
+	/**
+	 * GcrGnupgProcess:executable:
+	 *
+	 * Path to the gnupg executable, or %NULL for default.
+	 */
 	g_object_class_install_property (gobject_class, PROP_EXECUTABLE,
 	           g_param_spec_string ("executable", "Executable", "Gnupg Executable",
 	                                GPG_EXECUTABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
+	/**
+	 * GcrGnupgProcess::output-data:
+	 * @data: a #GByteArray of output data.
+	 *
+	 * Signal emitted when normal output data is available from the gnupg
+	 * process. The data does not necessarily come on line boundaries, and
+	 * won't be null-terminated.
+	 */
 	signals[OUTPUT_DATA] = g_signal_new ("output-data", GCR_TYPE_GNUPG_PROCESS,
 	           G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcrGnupgProcessClass, output_data),
 	           NULL, NULL, _gcr_marshal_VOID__BOXED,
 	           G_TYPE_NONE, 1, G_TYPE_BYTE_ARRAY);
 
+	/**
+	 * GcrGnupgProcess::error-line:
+	 * @line: a line of error output.
+	 *
+	 * Signal emitted when a line of error output is available from the
+	 * gnupg process.
+	 */
 	signals[ERROR_LINE] = g_signal_new ("error-line", GCR_TYPE_GNUPG_PROCESS,
 	           G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcrGnupgProcessClass, error_line),
 	           NULL, NULL, _gcr_marshal_VOID__STRING,
 	           G_TYPE_NONE, 1, G_TYPE_STRING);
 
+	/**
+	 * GcrGnupgProcess::status-record:
+	 * @record: a status record.
+	 *
+	 * Signal emitted when a status record is available from the gnupg process.
+	 */
 	signals[STATUS_RECORD] = g_signal_new ("status-record", GCR_TYPE_GNUPG_PROCESS,
 	           G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcrGnupgProcessClass, status_record),
 	           NULL, NULL, _gcr_marshal_VOID__BOXED,
 	           G_TYPE_NONE, 1, GCR_TYPE_RECORD);
 
+	/**
+	 * GcrGnupgProcess::attribute-data:
+	 * @data: a #GByteArray of attribute data.
+	 *
+	 * Signal emitted when attribute data is available from the gnupg
+	 * process.
+	 */
 	signals[ATTRIBUTE_DATA] = g_signal_new ("attribute-data", GCR_TYPE_GNUPG_PROCESS,
 	           G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcrGnupgProcessClass, attribute_data),
 	           NULL, NULL, _gcr_marshal_VOID__BOXED,
@@ -243,7 +293,7 @@ _gcr_gnupg_process_init_async (GAsyncResultIface *iface)
  * The executable will default to the compiled in path if a %NULL executable
  * argument is used.
  *
- * Returns: (transfer full) A newly allocated process.
+ * Returns: (transfer full): A newly allocated process.
  */
 GcrGnupgProcess*
 _gcr_gnupg_process_new (const gchar *directory, const gchar *executable)
@@ -393,10 +443,10 @@ on_gnupg_source_finalize (GSource *source)
 	GnupgSource *gnupg_source = (GnupgSource*)source;
 	gint i;
 
-	if (gnupg_source->cancel_sig) {
-		g_source_remove (gnupg_source->cancel_sig);
-		gnupg_source->cancel_sig = 0;
-	}
+	if (gnupg_source->cancel_sig)
+		g_signal_handler_disconnect (gnupg_source->cancellable, gnupg_source->cancel_sig);
+	if (gnupg_source->cancellable)
+		g_object_unref (gnupg_source->cancellable);
 
 	for (i = 0; i < NUM_FDS; ++i)
 		close_fd (&gnupg_source->polls[i].fd);
@@ -415,7 +465,7 @@ read_output (int fd, GByteArray *buffer)
 	guchar block[1024];
 	gssize result;
 
-	g_return_val_if_fail (fd >= 0, -1);
+	g_return_val_if_fail (fd >= 0, FALSE);
 
 	do {
 		result = read (fd, block, sizeof (block));
@@ -468,7 +518,7 @@ on_gnupg_source_dispatch (GSource *source, GSourceFunc unused, gpointer user_dat
 	GByteArray *buffer;
 	GPollFD *poll;
 
-	/* Standard input, no suport yet */
+	/* Standard input, no support yet */
 	poll = &gnupg_source->polls[FD_INPUT];
 	if (poll->fd >= 0 && poll->revents != 0) {
 		close_poll (source, poll);
@@ -519,7 +569,7 @@ on_gnupg_source_dispatch (GSource *source, GSourceFunc unused, gpointer user_dat
 			if (!read_output (poll->fd, buffer)) {
 				g_warning ("couldn't read output data from gnupg process");
 			} else if (buffer->len > 0) {
-				_gcr_debug ("received %d bytes of attribute data", (gint)buffer->len);
+				_gcr_debug ("received %d bytes of output data", (gint)buffer->len);
 				g_signal_emit (gnupg_source->process, signals[OUTPUT_DATA], 0, buffer);
 			}
 			g_byte_array_unref (buffer);
@@ -579,14 +629,14 @@ on_gnupg_process_child_exited (GPid pid, gint status, gpointer user_data)
 		code = WEXITSTATUS (status);
 		if (code != 0) {
 			error = g_error_new (G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
-			                     "Gnupg process exited with code: %d", code);
+			                     _("Gnupg process exited with code: %d"), code);
 		}
 	} else if (WIFSIGNALED (status)) {
 		code = WTERMSIG (status);
 		/* Ignore cases where we've signaled the process because we were cancelled */
 		if (!g_error_matches (self->pv->error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 			error = g_error_new (G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
-			                     "Gnupg process was terminated with signal: %d", code);
+			                     _("Gnupg process was terminated with signal: %d"), code);
 	}
 
 	/* Take this as the async result error */
@@ -596,7 +646,7 @@ on_gnupg_process_child_exited (GPid pid, gint status, gpointer user_data)
 
 	/* Already have an error, just print out message */
 	} else if (error) {
-		g_message ("%s", error->message);
+		g_warning ("%s", error->message);
 		g_error_free (error);
 	}
 
@@ -642,7 +692,7 @@ on_cancellable_cancelled (GCancellable *cancellable, gpointer user_data)
 	/* Set an error, which is respected when this actually completes. */
 	if (gnupg_source->process->pv->error == NULL)
 		gnupg_source->process->pv->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
-		                                                        "The operation was cancelled");
+		                                                        _("The operation was cancelled"));
 
 	complete_if_source_is_done (gnupg_source);
 }
@@ -650,11 +700,12 @@ on_cancellable_cancelled (GCancellable *cancellable, gpointer user_data)
 /**
  * _gcr_gnupg_process_run_async:
  * @self: The process
- * @argv: The arguments for the process, not including executable
- * @envp: (allow-none): The environment for new process.
+ * @argv: (array zero-terminated=1): The arguments for the process, not including executable, terminated with %NULL.
+ * @envp: (allow-none) (array zero-terminated=1): The environment for new process, terminated with %NULL.
  * @flags: Flags for starting the process.
  * @cancellable: (allow-none): Cancellation object
  * @callback: Will be called when operation completes.
+ * @user_data: (closure): Data passed to callback.
  *
  * Run the gpg process. Only one 'run' operation can run per GcrGnupgProcess
  * object. The GcrGnupgProcess:output_data and GcrGnupgProcess:error_line
@@ -688,6 +739,7 @@ _gcr_gnupg_process_run_async (GcrGnupgProcess *self, const gchar **argv, const g
 	g_return_if_fail (GCR_IS_GNUPG_PROCESS (self));
 	g_return_if_fail (argv);
 	g_return_if_fail (callback);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
 	g_return_if_fail (self->pv->running == FALSE);
 	g_return_if_fail (self->pv->complete == FALSE);
@@ -811,6 +863,7 @@ _gcr_gnupg_process_run_async (GcrGnupgProcess *self, const gchar **argv, const g
 	}
 
 	if (cancellable) {
+		gnupg_source->cancellable = g_object_ref (cancellable);
 		gnupg_source->cancel_sig = g_cancellable_connect (cancellable,
 		                                                  G_CALLBACK (on_cancellable_cancelled),
 		                                                  g_source_ref (source),
@@ -838,6 +891,8 @@ _gcr_gnupg_process_run_async (GcrGnupgProcess *self, const gchar **argv, const g
  * @error: Location to raise an error on failure.
  *
  * Get the result of running a gnupg process.
+ *
+ * Return value: Whether the Gnupg process was run or not.
  */
 gboolean
 _gcr_gnupg_process_run_finish (GcrGnupgProcess *self, GAsyncResult *result,
diff --git a/gcr/gcr-gnupg-process.h b/gcr/gcr-gnupg-process.h
index d3d0532..ecbab6d 100644
--- a/gcr/gcr-gnupg-process.h
+++ b/gcr/gcr-gnupg-process.h
@@ -61,12 +61,13 @@ struct _GcrGnupgProcessClass {
 };
 
 typedef enum {
+	GCR_GNUPG_PROCESS_NONE              = 0,
 	GCR_GNUPG_PROCESS_RESPECT_LOCALE    = 1 << 0,
 	GCR_GNUPG_PROCESS_WITH_STATUS       = 1 << 1,
 	GCR_GNUPG_PROCESS_WITH_ATTRIBUTES   = 1 << 2
 } GcrGnupgProcessFlags;
 
-GType               _gcr_gnupg_process_get_type                (void);
+GType               _gcr_gnupg_process_get_type                (void) G_GNUC_CONST;
 
 GcrGnupgProcess*    _gcr_gnupg_process_new                     (const gchar *directory,
                                                                 const gchar *executable);
diff --git a/gcr/tests/files/gnupg-mock/mock-status-and-attribute b/gcr/tests/files/gnupg-mock/mock-status-and-attribute
index 4df073a..abf8607 100755
--- a/gcr/tests/files/gnupg-mock/mock-status-and-attribute
+++ b/gcr/tests/files/gnupg-mock/mock-status-and-attribute
@@ -2,7 +2,7 @@
 
 # This script is used with test-gnupg-process
 # Needs to be run with /bin/bash in order to handle two digit
-# file descripter redirects
+# file descriptor redirects
 
 set -euf
 
diff --git a/gcr/tests/test-gnupg-process.c b/gcr/tests/test-gnupg-process.c
index 80dfe04..e9095f3 100644
--- a/gcr/tests/test-gnupg-process.c
+++ b/gcr/tests/test-gnupg-process.c
@@ -52,10 +52,8 @@ setup (Test *test, gconstpointer unused)
 static void
 teardown (Test *test, gconstpointer unused)
 {
-	if (test->result)
-		g_object_unref (test->result);
-	if (test->process)
-		g_object_unref (test->process);
+	g_assert (!test->result);
+	g_assert (!test->process);
 	if (test->output_buf)
 		g_string_free (test->output_buf, TRUE);
 	if (test->error_buf)
@@ -79,6 +77,8 @@ test_create (Test *test, gconstpointer unused)
 	g_object_get (test->process, "executable", &value, NULL);
 	g_assert_cmpstr (value, ==, "/path/to/executable");
 	g_free (value);
+
+	g_clear_object (&test->process);
 }
 
 static void
@@ -158,6 +158,7 @@ test_run_simple_output (Test *test, gconstpointer unused)
 {
 	const gchar *argv[] = { NULL };
 	GError *error = NULL;
+	gboolean ret;
 	gchar *script;
 
 	script = build_script_path ("mock-simple-output");
@@ -170,10 +171,14 @@ test_run_simple_output (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_no_error (error);
+	g_assert (ret == TRUE);
 
 	g_assert_cmpstr ("simple-output\n", ==, test->output_buf->str);
+
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 static void
@@ -182,6 +187,7 @@ test_run_simple_error (Test *test, gconstpointer unused)
 	const gchar *argv[] = { NULL };
 	GError *error = NULL;
 	gchar *script;
+	gboolean ret;
 
 	script = build_script_path ("mock-simple-error");
 	test->process = _gcr_gnupg_process_new (NULL, script);
@@ -193,10 +199,14 @@ test_run_simple_error (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_no_error (error);
+	g_assert (ret == TRUE);
 
 	g_assert_cmpstr ("line 1: more line 1\nline 2\nline 3\n", ==, test->error_buf->str);
+
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 static void
@@ -205,6 +215,7 @@ test_run_status_and_output (Test *test, gconstpointer unused)
 	const gchar *argv[] = { NULL };
 	GError *error = NULL;
 	gchar *script;
+	gboolean ret;
 
 	script = build_script_path ("mock-status-and-output");
 	test->process = _gcr_gnupg_process_new (NULL, script);
@@ -218,8 +229,9 @@ test_run_status_and_output (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_no_error (error);
+	g_assert (ret == TRUE);
 
 	g_assert (test->record);
 	g_assert_cmpstr (_gcr_record_get_raw (test->record, 0), ==, "SCHEMA");
@@ -229,6 +241,9 @@ test_run_status_and_output (Test *test, gconstpointer unused)
 	g_assert_cmpstr (_gcr_record_get_raw (test->record, 4), ==, "four");
 	g_assert_cmpstr (_gcr_record_get_raw (test->record, 5), ==, NULL);
 	g_assert_cmpstr ("Here's some output\nMore output\n", ==, test->output_buf->str);
+
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 static void
@@ -237,6 +252,7 @@ test_run_status_and_attribute (Test *test, gconstpointer unused)
 	const gchar *argv[] = { NULL };
 	GError *error = NULL;
 	gchar *script;
+	gboolean ret;
 
 	script = build_script_path ("mock-status-and-attribute");
 	test->process = _gcr_gnupg_process_new (NULL, script);
@@ -251,8 +267,9 @@ test_run_status_and_attribute (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_no_error (error);
+	g_assert (ret == TRUE);
 
 	g_assert (test->record);
 	g_assert_cmpstr (_gcr_record_get_raw (test->record, 0), ==, "SCHEMA");
@@ -262,6 +279,9 @@ test_run_status_and_attribute (Test *test, gconstpointer unused)
 	g_assert_cmpstr (_gcr_record_get_raw (test->record, 4), ==, "four");
 	g_assert_cmpstr (_gcr_record_get_raw (test->record, 5), ==, NULL);
 	g_assert_cmpstr ("1lc923g4laoeurc23rc241lcg2r23c4gr3", ==, test->attribute_buf->str);
+
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 
@@ -270,6 +290,7 @@ test_run_arguments_and_environment (Test *test, gconstpointer unused)
 {
 	GError *error = NULL;
 	gchar *script;
+	gboolean ret;
 
 	const gchar *argv[] = {
 		"-1", "value1",
@@ -294,11 +315,15 @@ test_run_arguments_and_environment (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_no_error (error);
+	g_assert (ret == TRUE);
 
 	g_assert_cmpstr ("value1\nvalue2\n", ==, test->output_buf->str);
 	g_assert_cmpstr ("VALUE1VALUE2\n", ==, test->error_buf->str);
+
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 static void
@@ -309,6 +334,7 @@ test_run_with_homedir (Test *test, gconstpointer unused)
 	gchar *script;
 	gchar *directory;
 	gchar *check;
+	gboolean ret;
 
 	directory = g_get_current_dir ();
 
@@ -322,13 +348,17 @@ test_run_with_homedir (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_no_error (error);
+	g_assert (ret == TRUE);
 
 	check = g_strdup_printf ("DIR: %s\n", directory);
 	g_assert_cmpstr (check, ==, test->output_buf->str);
 	g_free (check);
 	g_free (directory);
+
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 static void
@@ -337,6 +367,7 @@ test_run_bad_executable (Test *test, gconstpointer unused)
 	GError *error = NULL;
 	gchar *script;
 	const gchar *argv[] = { NULL };
+	gboolean ret;
 
 	script = build_script_path ("mock-invalid");
 	test->process = _gcr_gnupg_process_new (NULL, script);
@@ -346,9 +377,13 @@ test_run_bad_executable (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT);
 	g_clear_error (&error);
+	g_assert (ret == FALSE);
+
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 static void
@@ -357,6 +392,7 @@ test_run_fail_exit (Test *test, gconstpointer unused)
 	GError *error = NULL;
 	gchar *script;
 	const gchar *argv[] = { "55" };
+	gboolean ret;
 
 	script = build_script_path ("mock-fail-exit");
 	test->process = _gcr_gnupg_process_new (NULL, script);
@@ -366,10 +402,14 @@ test_run_fail_exit (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED);
 	g_assert_cmpstr (error->message, ==, "Gnupg process exited with code: 55");
 	g_clear_error (&error);
+	g_assert (ret == FALSE);
+
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 static void
@@ -378,6 +418,7 @@ test_run_fail_signal (Test *test, gconstpointer unused)
 	GError *error = NULL;
 	gchar *script;
 	const gchar *argv[] = { "15" };
+	gboolean ret;
 
 	script = build_script_path ("mock-fail-signal");
 	test->process = _gcr_gnupg_process_new (NULL, script);
@@ -387,10 +428,14 @@ test_run_fail_signal (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED);
 	g_assert_cmpstr (error->message, ==, "Gnupg process was terminated with signal: 15");
 	g_clear_error (&error);
+	g_assert (ret == FALSE);
+
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 static void
@@ -400,6 +445,7 @@ test_run_and_cancel (Test *test, gconstpointer unused)
 	gchar *script;
 	const gchar *argv[] = { "15" };
 	GCancellable *cancellable;
+	gboolean ret;
 
 	cancellable = g_cancellable_new ();
 
@@ -412,9 +458,51 @@ test_run_and_cancel (Test *test, gconstpointer unused)
 	egg_test_wait_until (500);
 
 	g_assert (test->result);
-	_gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
+	g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+	g_clear_error (&error);
+	g_assert (ret == FALSE);
+
+	g_object_unref (cancellable);
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
+}
+
+static void
+on_process_output_cancel (GcrGnupgProcess *process, GByteArray *buffer, gpointer user_data)
+{
+	GCancellable *cancellable = G_CANCELLABLE (user_data);
+	g_cancellable_cancel (cancellable);
+}
+
+static void
+test_run_and_cancel_later (Test *test, gconstpointer unused)
+{
+	GError *error = NULL;
+	gchar *script;
+	const gchar *argv[] = { "15" };
+	GCancellable *cancellable;
+	gboolean ret;
+
+	cancellable = g_cancellable_new ();
+
+	script = build_script_path ("mock-simple-output");
+	test->process = _gcr_gnupg_process_new (NULL, script);
+	g_signal_connect (test->process, "output-data", G_CALLBACK (on_process_output_cancel), cancellable);
+	g_free (script);
+
+	_gcr_gnupg_process_run_async (test->process, argv, NULL, 0, cancellable, on_async_ready, test);
+	egg_test_wait_until (500);
+
+	g_assert (test->result);
+	ret = _gcr_gnupg_process_run_finish (test->process, test->result, &error);
 	g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
 	g_clear_error (&error);
+	g_assert (ret == FALSE);
+
+	g_object_unref (cancellable);
+	g_clear_object (&test->result);
+	g_clear_object (&test->process);
 }
 
 int
@@ -441,6 +529,7 @@ main (int argc, char **argv)
 	g_test_add ("/gcr/gnupg-process/run_fail_exit", Test, NULL, setup, test_run_fail_exit, teardown);
 	g_test_add ("/gcr/gnupg-process/run_fail_signal", Test, NULL, setup, test_run_fail_signal, teardown);
 	g_test_add ("/gcr/gnupg-process/run_and_cancel", Test, NULL, setup, test_run_and_cancel, teardown);
+	g_test_add ("/gcr/gnupg-process/run_and_cancel_later", Test, NULL, setup, test_run_and_cancel_later, teardown);
 
 	return egg_tests_run_in_thread_with_loop ();
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]