[gnome-keyring: 2/3] gcr: Review changes for GcrGnupgProcess from Phillip Withnall
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring: 2/3] gcr: Review changes for GcrGnupgProcess from Phillip Withnall
- Date: Tue, 12 Jul 2011 10:56:15 +0000 (UTC)
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]