|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* gnome-keyring
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Copyright (C) 2011 Collabora Ltd.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
b00eeb |
* it under the terms of the GNU Lesser General Public License as
|
|
Packit |
b00eeb |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
b00eeb |
* the License, or (at your option) any later version.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
b00eeb |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b00eeb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
b00eeb |
* Lesser General Public License for more details.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
b00eeb |
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Author: Stef Walter <stfew@collabora.co.uk>
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "config.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "gcr-mock-prompter.h"
|
|
Packit |
b00eeb |
#include "gcr-prompt.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "egg/egg-error.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include <gobject/gvaluecollector.h>
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include <string.h>
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* SECTION:gcr-mock-prompter
|
|
Packit |
b00eeb |
* @title: GcrMockPrompter
|
|
Packit |
b00eeb |
* @short_description: a mock GcrSystemPrompter for testing
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* A mock GcrSystemPrompter used for testing against.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Use gcr_mock_prompter_start() to start the mock prompter in another
|
|
Packit |
b00eeb |
* thread. The returned string is the dbus address of the mock prompter.
|
|
Packit |
b00eeb |
* You can pass this to gcr_system_prompt_open() as the prompter bus name.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Use the gcr_mock_prompter_expect_confirm_ok() function and friends before
|
|
Packit |
b00eeb |
* prompting to verify that the prompts are displayed as expected, and to
|
|
Packit |
b00eeb |
* provide a response.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
GType _gcr_mock_prompt_get_type (void) G_GNUC_CONST;
|
|
Packit |
b00eeb |
#define GCR_TYPE_MOCK_PROMPT (_gcr_mock_prompt_get_type ())
|
|
Packit |
b00eeb |
#define GCR_MOCK_PROMPT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_MOCK_PROMPT, GcrMockPrompt))
|
|
Packit |
b00eeb |
#define GCR_IS_MOCK_PROMPT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_MOCK_PROMPT))
|
|
Packit |
b00eeb |
#define GCR_IS_MOCK_PROMPT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_MOCK_PROMPT))
|
|
Packit |
b00eeb |
#define GCR_MOCK_PROMPT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_MOCK_PROMPT, GcrMockPromptClass))
|
|
Packit |
b00eeb |
#define GCR_MOCK_PROMPT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_MOCK_PROMPT, GcrMockPromptClass))
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
typedef struct _GcrMockPrompt GcrMockPrompt;
|
|
Packit |
b00eeb |
typedef struct _GcrMockPromptClass GcrMockPromptClass;
|
|
Packit |
b00eeb |
typedef struct _GcrMockPromptPrivate GcrMockPromptPrivate;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
enum {
|
|
Packit |
b00eeb |
PROP_0,
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
PROP_TITLE,
|
|
Packit |
b00eeb |
PROP_MESSAGE,
|
|
Packit |
b00eeb |
PROP_DESCRIPTION,
|
|
Packit |
b00eeb |
PROP_WARNING,
|
|
Packit |
b00eeb |
PROP_PASSWORD_NEW,
|
|
Packit |
b00eeb |
PROP_PASSWORD_STRENGTH,
|
|
Packit |
b00eeb |
PROP_CHOICE_LABEL,
|
|
Packit |
b00eeb |
PROP_CHOICE_CHOSEN,
|
|
Packit |
b00eeb |
PROP_CALLER_WINDOW,
|
|
Packit |
b00eeb |
PROP_CONTINUE_LABEL,
|
|
Packit |
b00eeb |
PROP_CANCEL_LABEL,
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
struct _GcrMockPrompt {
|
|
Packit |
b00eeb |
GObject parent;
|
|
Packit |
b00eeb |
GHashTable *properties;
|
|
Packit |
b00eeb |
gboolean disposed;
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
struct _GcrMockPromptClass {
|
|
Packit |
b00eeb |
GObjectClass parent_class;
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
typedef struct {
|
|
Packit |
b00eeb |
gboolean close;
|
|
Packit |
b00eeb |
gboolean proceed;
|
|
Packit |
b00eeb |
gchar *password;
|
|
Packit |
b00eeb |
GList *properties;
|
|
Packit |
b00eeb |
} MockResponse;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
typedef struct {
|
|
Packit |
b00eeb |
/* Owned by the calling thread */
|
|
Packit |
b00eeb |
GMutex *mutex;
|
|
Packit |
b00eeb |
GCond *start_cond;
|
|
Packit |
b00eeb |
GThread *thread;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
guint delay_msec;
|
|
Packit |
b00eeb |
GQueue responses;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Owned by the prompter thread*/
|
|
Packit |
b00eeb |
GcrSystemPrompter *prompter;
|
|
Packit |
b00eeb |
GDBusConnection *connection;
|
|
Packit |
b00eeb |
GMainLoop *loop;
|
|
Packit |
b00eeb |
} ThreadData;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gint prompts_a_prompting = 0;
|
|
Packit |
b00eeb |
static ThreadData *running = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void gcr_mock_prompt_iface (GcrPromptIface *iface);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_DEFINE_TYPE_WITH_CODE (GcrMockPrompt, _gcr_mock_prompt, G_TYPE_OBJECT,
|
|
Packit |
b00eeb |
G_IMPLEMENT_INTERFACE (GCR_TYPE_PROMPT, gcr_mock_prompt_iface);
|
|
Packit |
b00eeb |
);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
mock_property_free (gpointer data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GParameter *param = data;
|
|
Packit |
b00eeb |
g_value_unset (¶m->value);
|
|
Packit |
b00eeb |
g_free (param);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
mock_response_free (gpointer data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
MockResponse *response = data;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (response == NULL)
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_free (response->password);
|
|
Packit |
b00eeb |
g_list_free_full (response->properties, mock_property_free);
|
|
Packit |
b00eeb |
g_free (response);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
blank_string_property (GHashTable *properties,
|
|
Packit |
b00eeb |
const gchar *property)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GParameter *param;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
param = g_new0 (GParameter, 1);
|
|
Packit |
b00eeb |
param->name = property;
|
|
Packit |
b00eeb |
g_value_init (¶m->value, G_TYPE_STRING);
|
|
Packit |
b00eeb |
g_value_set_string (¶m->value, "");
|
|
Packit |
b00eeb |
g_hash_table_insert (properties, (gpointer)param->name, param);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
blank_boolean_property (GHashTable *properties,
|
|
Packit |
b00eeb |
const gchar *property)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GParameter *param;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
param = g_new0 (GParameter, 1);
|
|
Packit |
b00eeb |
param->name = property;
|
|
Packit |
b00eeb |
g_value_init (¶m->value, G_TYPE_BOOLEAN);
|
|
Packit |
b00eeb |
g_value_set_boolean (¶m->value, FALSE);
|
|
Packit |
b00eeb |
g_hash_table_insert (properties, (gpointer)param->name, param);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
blank_int_property (GHashTable *properties,
|
|
Packit |
b00eeb |
const gchar *property)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GParameter *param;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
param = g_new0 (GParameter, 1);
|
|
Packit |
b00eeb |
param->name = property;
|
|
Packit |
b00eeb |
g_value_init (¶m->value, G_TYPE_INT);
|
|
Packit |
b00eeb |
g_value_set_int (¶m->value, 0);
|
|
Packit |
b00eeb |
g_hash_table_insert (properties, (gpointer)param->name, param);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_mock_prompt_init (GcrMockPrompt *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_atomic_int_add (&prompts_a_prompting, 1);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
Packit |
b00eeb |
NULL, mock_property_free);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
blank_string_property (self->properties, "title");
|
|
Packit |
b00eeb |
blank_string_property (self->properties, "message");
|
|
Packit |
b00eeb |
blank_string_property (self->properties, "description");
|
|
Packit |
b00eeb |
blank_string_property (self->properties, "warning");
|
|
Packit |
b00eeb |
blank_string_property (self->properties, "choice-label");
|
|
Packit |
b00eeb |
blank_string_property (self->properties, "caller-window");
|
|
Packit |
b00eeb |
blank_string_property (self->properties, "continue-label");
|
|
Packit |
b00eeb |
blank_string_property (self->properties, "cancel-label");
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
blank_boolean_property (self->properties, "choice-chosen");
|
|
Packit |
b00eeb |
blank_boolean_property (self->properties, "password-new");
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
blank_int_property (self->properties, "password-strength");
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_mock_prompt_set_property (GObject *obj,
|
|
Packit |
b00eeb |
guint prop_id,
|
|
Packit |
b00eeb |
const GValue *value,
|
|
Packit |
b00eeb |
GParamSpec *pspec)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMockPrompt *self = GCR_MOCK_PROMPT (obj);
|
|
Packit |
b00eeb |
GParameter *param;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (prop_id) {
|
|
Packit |
b00eeb |
case PROP_TITLE:
|
|
Packit |
b00eeb |
case PROP_MESSAGE:
|
|
Packit |
b00eeb |
case PROP_DESCRIPTION:
|
|
Packit |
b00eeb |
case PROP_WARNING:
|
|
Packit |
b00eeb |
case PROP_PASSWORD_NEW:
|
|
Packit |
b00eeb |
case PROP_CHOICE_LABEL:
|
|
Packit |
b00eeb |
case PROP_CHOICE_CHOSEN:
|
|
Packit |
b00eeb |
case PROP_CALLER_WINDOW:
|
|
Packit |
b00eeb |
case PROP_CONTINUE_LABEL:
|
|
Packit |
b00eeb |
case PROP_CANCEL_LABEL:
|
|
Packit |
b00eeb |
param = g_new0 (GParameter, 1);
|
|
Packit |
b00eeb |
param->name = pspec->name;
|
|
Packit |
b00eeb |
g_value_init (¶m->value, pspec->value_type);
|
|
Packit |
b00eeb |
g_value_copy (value, ¶m->value);
|
|
Packit |
b00eeb |
g_hash_table_replace (self->properties, (gpointer)param->name, param);
|
|
Packit |
b00eeb |
g_object_notify (G_OBJECT (self), param->name);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_mock_prompt_get_property (GObject *obj,
|
|
Packit |
b00eeb |
guint prop_id,
|
|
Packit |
b00eeb |
GValue *value,
|
|
Packit |
b00eeb |
GParamSpec *pspec)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMockPrompt *self = GCR_MOCK_PROMPT (obj);
|
|
Packit |
b00eeb |
GParameter *param;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (prop_id) {
|
|
Packit |
b00eeb |
case PROP_TITLE:
|
|
Packit |
b00eeb |
case PROP_MESSAGE:
|
|
Packit |
b00eeb |
case PROP_DESCRIPTION:
|
|
Packit |
b00eeb |
case PROP_WARNING:
|
|
Packit |
b00eeb |
case PROP_PASSWORD_NEW:
|
|
Packit |
b00eeb |
case PROP_PASSWORD_STRENGTH:
|
|
Packit |
b00eeb |
case PROP_CHOICE_LABEL:
|
|
Packit |
b00eeb |
case PROP_CHOICE_CHOSEN:
|
|
Packit |
b00eeb |
case PROP_CALLER_WINDOW:
|
|
Packit |
b00eeb |
case PROP_CONTINUE_LABEL:
|
|
Packit |
b00eeb |
case PROP_CANCEL_LABEL:
|
|
Packit |
b00eeb |
param = g_hash_table_lookup (self->properties, pspec->name);
|
|
Packit |
b00eeb |
g_return_if_fail (param != NULL);
|
|
Packit |
b00eeb |
g_value_copy (¶m->value, value);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_mock_prompt_dispose (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMockPrompt *self = GCR_MOCK_PROMPT (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (!self->disposed) {
|
|
Packit |
b00eeb |
g_atomic_int_add (&prompts_a_prompting, -1);
|
|
Packit |
b00eeb |
self->disposed = TRUE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (_gcr_mock_prompt_parent_class)->dispose (obj);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_mock_prompt_finalize (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMockPrompt *self = GCR_MOCK_PROMPT (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_hash_table_destroy(self->properties);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (_gcr_mock_prompt_parent_class)->finalize (obj);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
value_equal (const GValue *a, const GValue *b)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
gboolean ret = FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (G_VALUE_TYPE (a)) {
|
|
Packit |
b00eeb |
case G_TYPE_BOOLEAN:
|
|
Packit |
b00eeb |
ret = (g_value_get_boolean (a) == g_value_get_boolean (b));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case G_TYPE_UCHAR:
|
|
Packit |
b00eeb |
ret = (g_value_get_uchar (a) == g_value_get_uchar (b));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case G_TYPE_INT:
|
|
Packit |
b00eeb |
ret = (g_value_get_int (a) == g_value_get_int (b));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case G_TYPE_UINT:
|
|
Packit |
b00eeb |
ret = (g_value_get_uint (a) == g_value_get_uint (b));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case G_TYPE_INT64:
|
|
Packit |
b00eeb |
ret = (g_value_get_int64 (a) == g_value_get_int64 (b));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case G_TYPE_UINT64:
|
|
Packit |
b00eeb |
ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case G_TYPE_DOUBLE:
|
|
Packit |
b00eeb |
ret = (g_value_get_double (a) == g_value_get_double (b));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case G_TYPE_STRING:
|
|
Packit |
b00eeb |
ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
g_critical ("no support for comparing of type %s", g_type_name (G_VALUE_TYPE (a)));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return ret;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
prompt_set_or_check_properties (GcrMockPrompt *self,
|
|
Packit |
b00eeb |
GList *properties)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GValue value = G_VALUE_INIT;
|
|
Packit |
b00eeb |
GObjectClass *object_class;
|
|
Packit |
b00eeb |
GParameter *param;
|
|
Packit |
b00eeb |
GParamSpec *spec;
|
|
Packit |
b00eeb |
GList *l;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
object_class = G_OBJECT_GET_CLASS (self);
|
|
Packit |
b00eeb |
for (l = properties; l != NULL; l = g_list_next (l)) {
|
|
Packit |
b00eeb |
param = l->data;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
spec = g_object_class_find_property (object_class, param->name);
|
|
Packit |
b00eeb |
g_assert (spec != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* For these we set the value */
|
|
Packit |
b00eeb |
if (g_str_equal (param->name, "choice-chosen")) {
|
|
Packit |
b00eeb |
g_object_set_property (G_OBJECT (self), param->name, ¶m->value);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* For others we check that the value is correct */
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_value_init (&value, G_VALUE_TYPE (¶m->value));
|
|
Packit |
b00eeb |
g_object_get_property (G_OBJECT (self), param->name, &value);
|
|
Packit |
b00eeb |
if (!value_equal (&value, ¶m->value)) {
|
|
Packit |
b00eeb |
gchar *expected = g_strdup_value_contents (¶m->value);
|
|
Packit |
b00eeb |
gchar *actual = g_strdup_value_contents (&value);
|
|
Packit |
b00eeb |
g_critical ("expected prompt property '%s' to be %s, but it "
|
|
Packit |
b00eeb |
"is instead %s", param->name, expected, actual);
|
|
Packit |
b00eeb |
g_free (expected);
|
|
Packit |
b00eeb |
g_free (actual);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
g_value_unset (&value);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
_gcr_mock_prompt_class_init (GcrMockPromptClass *klass)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gobject_class->get_property = _gcr_mock_prompt_get_property;
|
|
Packit |
b00eeb |
gobject_class->set_property = _gcr_mock_prompt_set_property;
|
|
Packit |
b00eeb |
gobject_class->dispose = _gcr_mock_prompt_dispose;
|
|
Packit |
b00eeb |
gobject_class->finalize = _gcr_mock_prompt_finalize;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_TITLE, "title");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_MESSAGE, "message");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_WARNING, "warning");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CALLER_WINDOW, "caller-window");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CHOICE_LABEL, "choice-label");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CHOICE_CHOSEN, "choice-chosen");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_PASSWORD_NEW, "password-new");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_PASSWORD_STRENGTH, "password-strength");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CONTINUE_LABEL, "continue-label");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CANCEL_LABEL, "cancel-label");
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
on_timeout_complete (gpointer data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res = data;
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
on_timeout_complete_and_close (gpointer data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res = data;
|
|
Packit |
b00eeb |
GcrPrompt *prompt = GCR_PROMPT (g_async_result_get_source_object (data));
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
gcr_prompt_close (prompt);
|
|
Packit |
b00eeb |
g_object_unref (prompt);
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
destroy_unref_source (gpointer source)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
if (!g_source_is_destroyed (source))
|
|
Packit |
b00eeb |
g_source_destroy (source);
|
|
Packit |
b00eeb |
g_source_unref (source);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_mock_prompt_confirm_async (GcrPrompt *prompt,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMockPrompt *self = GCR_MOCK_PROMPT (prompt);
|
|
Packit |
b00eeb |
GSourceFunc complete_func = on_timeout_complete;
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
MockResponse *response;
|
|
Packit |
b00eeb |
GSource *source;
|
|
Packit |
b00eeb |
guint delay_msec;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
delay_msec = running->delay_msec;
|
|
Packit |
b00eeb |
response = g_queue_pop_head (&running->responses);
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = g_simple_async_result_new (G_OBJECT (prompt), callback, user_data,
|
|
Packit |
b00eeb |
gcr_mock_prompt_confirm_async);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (response == NULL) {
|
|
Packit |
b00eeb |
g_critical ("password prompt requested, but not expected");
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gboolean (res, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else if (response->close) {
|
|
Packit |
b00eeb |
complete_func = on_timeout_complete_and_close;
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gboolean (res, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else if (response->password) {
|
|
Packit |
b00eeb |
g_critical ("confirmation prompt requested, but password prompt expected");
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gboolean (res, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
prompt_set_or_check_properties (self, response->properties);
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gboolean (res, response->proceed);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (delay_msec > 0)
|
|
Packit |
b00eeb |
source = g_timeout_source_new (delay_msec);
|
|
Packit |
b00eeb |
else
|
|
Packit |
b00eeb |
source = g_idle_source_new ();
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_source_set_callback (source, complete_func, g_object_ref (res), g_object_unref);
|
|
Packit |
b00eeb |
g_source_attach (source, g_main_context_get_thread_default ());
|
|
Packit |
b00eeb |
g_object_set_data_full (G_OBJECT (self), "delay-source", source, destroy_unref_source);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
mock_response_free (response);
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GcrPromptReply
|
|
Packit |
b00eeb |
gcr_mock_prompt_confirm_finish (GcrPrompt *prompt,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (prompt),
|
|
Packit |
b00eeb |
gcr_mock_prompt_confirm_async), GCR_PROMPT_REPLY_CANCEL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (result)) ?
|
|
Packit |
b00eeb |
GCR_PROMPT_REPLY_CONTINUE : GCR_PROMPT_REPLY_CANCEL;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
ensure_password_strength (GcrMockPrompt *self,
|
|
Packit |
b00eeb |
const gchar *password)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GParameter *param;
|
|
Packit |
b00eeb |
gint strength;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
strength = strlen (password) > 0 ? 1 : 0;
|
|
Packit |
b00eeb |
param = g_new0 (GParameter, 1);
|
|
Packit |
b00eeb |
param->name = "password-strength";
|
|
Packit |
b00eeb |
g_value_init (¶m->value, G_TYPE_INT);
|
|
Packit |
b00eeb |
g_value_set_int (¶m->value, strength);
|
|
Packit |
b00eeb |
g_hash_table_replace (self->properties, (gpointer)param->name, param);
|
|
Packit |
b00eeb |
g_object_notify (G_OBJECT (self), param->name);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_mock_prompt_password_async (GcrPrompt *prompt,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrMockPrompt *self = GCR_MOCK_PROMPT (prompt);
|
|
Packit |
b00eeb |
GSourceFunc complete_func = on_timeout_complete;
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
MockResponse *response;
|
|
Packit |
b00eeb |
GSource *source;
|
|
Packit |
b00eeb |
guint delay_msec;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
delay_msec = running->delay_msec;
|
|
Packit |
b00eeb |
response = g_queue_pop_head (&running->responses);
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = g_simple_async_result_new (G_OBJECT (prompt), callback, user_data,
|
|
Packit |
b00eeb |
gcr_mock_prompt_password_async);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (response == NULL) {
|
|
Packit |
b00eeb |
g_critical ("password prompt requested, but not expected");
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else if (response->close) {
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
|
|
Packit |
b00eeb |
complete_func = on_timeout_complete_and_close;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else if (!response->password) {
|
|
Packit |
b00eeb |
g_critical ("password prompt requested, but confirmation prompt expected");
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else if (!response->proceed) {
|
|
Packit |
b00eeb |
prompt_set_or_check_properties (self, response->properties);
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
ensure_password_strength (self, response->password);
|
|
Packit |
b00eeb |
prompt_set_or_check_properties (self, response->properties);
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gpointer (res, response->password, g_free);
|
|
Packit |
b00eeb |
response->password = NULL;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
mock_response_free (response);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (delay_msec > 0)
|
|
Packit |
b00eeb |
source = g_timeout_source_new (delay_msec);
|
|
Packit |
b00eeb |
else
|
|
Packit |
b00eeb |
source = g_idle_source_new ();
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_source_set_callback (source, complete_func, g_object_ref (res), g_object_unref);
|
|
Packit |
b00eeb |
g_source_attach (source, g_main_context_get_thread_default ());
|
|
Packit |
b00eeb |
g_object_set_data_full (G_OBJECT (self), "delay-source", source, destroy_unref_source);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static const gchar *
|
|
Packit |
b00eeb |
gcr_mock_prompt_password_finish (GcrPrompt *prompt,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (prompt),
|
|
Packit |
b00eeb |
gcr_mock_prompt_password_async), NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_mock_prompt_iface (GcrPromptIface *iface)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
iface->prompt_confirm_async = gcr_mock_prompt_confirm_async;
|
|
Packit |
b00eeb |
iface->prompt_confirm_finish = gcr_mock_prompt_confirm_finish;
|
|
Packit |
b00eeb |
iface->prompt_password_async = gcr_mock_prompt_password_async;
|
|
Packit |
b00eeb |
iface->prompt_password_finish = gcr_mock_prompt_password_finish;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GList *
|
|
Packit |
b00eeb |
build_properties (GObjectClass *object_class,
|
|
Packit |
b00eeb |
const gchar *first_property,
|
|
Packit |
b00eeb |
va_list var_args)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GList *result = NULL;
|
|
Packit |
b00eeb |
const gchar *name;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
name = first_property;
|
|
Packit |
b00eeb |
while (name) {
|
|
Packit |
b00eeb |
GValue value = G_VALUE_INIT;
|
|
Packit |
b00eeb |
GParameter *parameter;
|
|
Packit |
b00eeb |
GParamSpec *spec;
|
|
Packit |
b00eeb |
gchar *error = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
spec = g_object_class_find_property (object_class, name);
|
|
Packit |
b00eeb |
if (spec == NULL) {
|
|
Packit |
b00eeb |
g_warning ("prompt object class has no property named '%s'", name);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if ((spec->flags & G_PARAM_CONSTRUCT_ONLY) && !(spec->flags & G_PARAM_READABLE)) {
|
|
Packit |
b00eeb |
g_warning ("prompt property '%s' can't be set after construction", name);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_VALUE_COLLECT_INIT (&value, spec->value_type, var_args, 0, &error);
|
|
Packit |
b00eeb |
if (error != NULL) {
|
|
Packit |
b00eeb |
g_warning ("%s", error);
|
|
Packit |
b00eeb |
g_free (error);
|
|
Packit |
b00eeb |
g_value_unset (&value);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
parameter = g_new0 (GParameter, 1);
|
|
Packit |
b00eeb |
parameter->name = g_intern_string (name);
|
|
Packit |
b00eeb |
memcpy (¶meter->value, &value, sizeof (value));
|
|
Packit |
b00eeb |
result = g_list_prepend (result, parameter);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
name = va_arg (var_args, gchar *);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return result;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_is_prompting:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Check if the mock prompter is showing any prompts.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: whether prompting
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
gboolean
|
|
Packit |
b00eeb |
gcr_mock_prompter_is_prompting (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
return g_atomic_int_get (&prompts_a_prompting) > 0;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_get_delay_msec:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Get the delay in milliseconds before the mock prompter completes
|
|
Packit |
b00eeb |
* an expected prompt.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: the delay
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
guint
|
|
Packit |
b00eeb |
gcr_mock_prompter_get_delay_msec (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
guint delay_msec;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
delay_msec = running->delay_msec;
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return delay_msec;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_set_delay_msec:
|
|
Packit |
b00eeb |
* @delay_msec: prompt response delay in milliseconds
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Set the delay in milliseconds before the mock prompter completes
|
|
Packit |
b00eeb |
* an expected prompt.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_mock_prompter_set_delay_msec (guint delay_msec)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
running->delay_msec = delay_msec;
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_expect_confirm_ok:
|
|
Packit |
b00eeb |
* @first_property_name: the first property name in the argument list or %NULL
|
|
Packit |
b00eeb |
* @...: properties to expect
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Queue an expected response on the mock prompter.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Expects a confirmation prompt, and then confirms that prompt by
|
|
Packit |
b00eeb |
* simulating a click on the ok button.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Additional property pairs for the prompt can be added in the argument
|
|
Packit |
b00eeb |
* list, in the same way that you would with g_object_new().
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* If the "choice-chosen" property is specified then that value will be
|
|
Packit |
b00eeb |
* set on the prompt as if the user had changed the value.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* All other properties will be checked against the prompt, and an error
|
|
Packit |
b00eeb |
* will occur if they do not match the value set on the prompt.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_mock_prompter_expect_confirm_ok (const gchar *first_property_name,
|
|
Packit |
b00eeb |
...)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
MockResponse *response;
|
|
Packit |
b00eeb |
gpointer klass;
|
|
Packit |
b00eeb |
va_list var_args;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
response = g_new0 (MockResponse, 1);
|
|
Packit |
b00eeb |
response->password = NULL;
|
|
Packit |
b00eeb |
response->proceed = TRUE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
klass = g_type_class_ref (GCR_TYPE_MOCK_PROMPT);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
va_start (var_args, first_property_name);
|
|
Packit |
b00eeb |
response->properties = build_properties (G_OBJECT_CLASS (klass), first_property_name, var_args);
|
|
Packit |
b00eeb |
va_end (var_args);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_type_class_unref (klass);
|
|
Packit |
b00eeb |
g_queue_push_tail (&running->responses, response);
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_expect_confirm_cancel:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Queue an expected response on the mock prompter.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Expects a confirmation prompt, and then cancels that prompt.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_mock_prompter_expect_confirm_cancel (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
MockResponse *response;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
response = g_new0 (MockResponse, 1);
|
|
Packit |
b00eeb |
response->password = NULL;
|
|
Packit |
b00eeb |
response->proceed = FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_queue_push_tail (&running->responses, response);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_expect_password_ok:
|
|
Packit |
b00eeb |
* @password: the password to return from the prompt
|
|
Packit |
b00eeb |
* @first_property_name: the first property name in the argument list or %NULL
|
|
Packit |
b00eeb |
* @...: properties to expect
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Queue an expected response on the mock prompter.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Expects a password prompt, and returns @password as if the user had entered
|
|
Packit |
b00eeb |
* it and clicked the ok button.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Additional property pairs for the prompt can be added in the argument
|
|
Packit |
b00eeb |
* list, in the same way that you would with g_object_new().
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* If the "choice-chosen" property is specified then that value will be
|
|
Packit |
b00eeb |
* set on the prompt as if the user had changed the value.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* All other properties will be checked against the prompt, and an error
|
|
Packit |
b00eeb |
* will occur if they do not match the value set on the prompt.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_mock_prompter_expect_password_ok (const gchar *password,
|
|
Packit |
b00eeb |
const gchar *first_property_name,
|
|
Packit |
b00eeb |
...)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
MockResponse *response;
|
|
Packit |
b00eeb |
gpointer klass;
|
|
Packit |
b00eeb |
va_list var_args;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
g_assert (password != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
response = g_new0 (MockResponse, 1);
|
|
Packit |
b00eeb |
response->password = g_strdup (password);
|
|
Packit |
b00eeb |
response->proceed = TRUE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
klass = g_type_class_ref (GCR_TYPE_MOCK_PROMPT);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
va_start (var_args, first_property_name);
|
|
Packit |
b00eeb |
response->properties = build_properties (G_OBJECT_CLASS (klass), first_property_name, var_args);
|
|
Packit |
b00eeb |
va_end (var_args);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_type_class_unref (klass);
|
|
Packit |
b00eeb |
g_queue_push_tail (&running->responses, response);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_expect_password_cancel:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Queue an expected response on the mock prompter.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Expects a password prompt, and then cancels that prompt.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_mock_prompter_expect_password_cancel (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
MockResponse *response;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
response = g_new0 (MockResponse, 1);
|
|
Packit |
b00eeb |
response->password = g_strdup ("");
|
|
Packit |
b00eeb |
response->proceed = FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_queue_push_tail (&running->responses, response);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_expect_close:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Queue an expected response on the mock prompter.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Expects any prompt, and closes the prompt when it gets it.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_mock_prompter_expect_close (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
MockResponse *response;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
response = g_new0 (MockResponse, 1);
|
|
Packit |
b00eeb |
response->close = TRUE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_queue_push_tail (&running->responses, response);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_is_expecting:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Check if the mock prompter is expecting a response. This will be %TRUE
|
|
Packit |
b00eeb |
* when one of the <literal>gcr_mock_prompter_expect_xxx()</literal>
|
|
Packit |
b00eeb |
* functions have been used to queue an expected prompt, but that prompt
|
|
Packit |
b00eeb |
* response has not be 'used' yet.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: whether expecting a prompt
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
gboolean
|
|
Packit |
b00eeb |
gcr_mock_prompter_is_expecting (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
gboolean expecting;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
expecting = !g_queue_is_empty (&running->responses);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return expecting;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
on_idle_signal_cond (gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GCond *cond = user_data;
|
|
Packit |
b00eeb |
g_cond_signal (cond);
|
|
Packit |
b00eeb |
return FALSE; /* Don't run again */
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* These next few functions test the new-prompt signals of
|
|
Packit |
b00eeb |
* GcrSystemPrompter. They should probably be in tests, but
|
|
Packit |
b00eeb |
* don't fit there nicely.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
static GcrPrompt *
|
|
Packit |
b00eeb |
on_new_prompt_skipped (GcrSystemPrompter *prompter,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_SYSTEM_PROMPTER (prompter), NULL);
|
|
Packit |
b00eeb |
return NULL;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GcrPrompt *
|
|
Packit |
b00eeb |
on_new_prompt_creates (GcrSystemPrompter *prompter,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_SYSTEM_PROMPTER (prompter), NULL);
|
|
Packit |
b00eeb |
return g_object_new (GCR_TYPE_MOCK_PROMPT, NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GcrPrompt *
|
|
Packit |
b00eeb |
on_new_prompt_not_called (GcrSystemPrompter *prompter,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_SYSTEM_PROMPTER (prompter), NULL);
|
|
Packit |
b00eeb |
g_return_val_if_reached (NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gpointer
|
|
Packit |
b00eeb |
mock_prompter_thread (gpointer data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
ThreadData *thread_data = data;
|
|
Packit |
b00eeb |
GDBusConnection *connection = NULL;
|
|
Packit |
b00eeb |
GMainContext *context;
|
|
Packit |
b00eeb |
GError *error = NULL;
|
|
Packit |
b00eeb |
GSource *idle;
|
|
Packit |
b00eeb |
gchar *address;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (thread_data->mutex);
|
|
Packit |
b00eeb |
context = g_main_context_new ();
|
|
Packit |
b00eeb |
g_main_context_push_thread_default (context);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* Random choice between signals, and prompt-gtype style of creating
|
|
Packit |
b00eeb |
* GcrPrompt objects.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (g_random_boolean ()) {
|
|
Packit |
b00eeb |
/* Allows GcrSystemPrompter to create the prompts directly */
|
|
Packit |
b00eeb |
thread_data->prompter = gcr_system_prompter_new (GCR_SYSTEM_PROMPTER_SINGLE,
|
|
Packit |
b00eeb |
GCR_TYPE_MOCK_PROMPT);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
/* Create the prompt objects in signal handler */
|
|
Packit |
b00eeb |
thread_data->prompter = gcr_system_prompter_new (GCR_SYSTEM_PROMPTER_SINGLE, 0);
|
|
Packit |
b00eeb |
g_signal_connect (thread_data->prompter, "new-prompt", G_CALLBACK (on_new_prompt_skipped), NULL);
|
|
Packit |
b00eeb |
g_signal_connect (thread_data->prompter, "new-prompt", G_CALLBACK (on_new_prompt_creates), NULL);
|
|
Packit |
b00eeb |
g_signal_connect (thread_data->prompter, "new-prompt", G_CALLBACK (on_new_prompt_not_called), NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
|
Packit |
b00eeb |
if (error == NULL) {
|
|
Packit |
b00eeb |
connection = g_dbus_connection_new_for_address_sync (address,
|
|
Packit |
b00eeb |
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
|
|
Packit |
b00eeb |
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
|
|
Packit |
b00eeb |
NULL, NULL, &error);
|
|
Packit |
b00eeb |
if (error == NULL) {
|
|
Packit |
b00eeb |
thread_data->connection = connection;
|
|
Packit |
b00eeb |
gcr_system_prompter_register (GCR_SYSTEM_PROMPTER (thread_data->prompter),
|
|
Packit |
b00eeb |
connection);
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_critical ("couldn't create connection: %s", error->message);
|
|
Packit |
b00eeb |
g_error_free (error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_free (address);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (error != NULL) {
|
|
Packit |
b00eeb |
g_critical ("mock prompter couldn't get session bus address: %s",
|
|
Packit |
b00eeb |
egg_error_message (error));
|
|
Packit |
b00eeb |
g_clear_error (&error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
thread_data->loop = g_main_loop_new (context, FALSE);
|
|
Packit |
b00eeb |
g_mutex_unlock (thread_data->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
idle = g_idle_source_new ();
|
|
Packit |
b00eeb |
g_source_set_callback (idle, on_idle_signal_cond, thread_data->start_cond, NULL);
|
|
Packit |
b00eeb |
g_source_attach (idle, context);
|
|
Packit |
b00eeb |
g_source_unref (idle);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_loop_run (thread_data->loop);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (thread_data->mutex);
|
|
Packit |
b00eeb |
g_main_context_pop_thread_default (context);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gcr_system_prompter_unregister (thread_data->prompter, TRUE);
|
|
Packit |
b00eeb |
g_object_unref (thread_data->prompter);
|
|
Packit |
b00eeb |
thread_data->prompter = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (connection) {
|
|
Packit |
b00eeb |
thread_data->connection = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (!g_dbus_connection_is_closed (connection)) {
|
|
Packit |
b00eeb |
if (!g_dbus_connection_flush_sync (connection, NULL, &error)) {
|
|
Packit |
b00eeb |
g_critical ("connection flush failed: %s", error->message);
|
|
Packit |
b00eeb |
g_error_free (error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
if (!g_dbus_connection_close_sync (connection, NULL, &error)) {
|
|
Packit |
b00eeb |
g_critical ("connection close failed: %s", error->message);
|
|
Packit |
b00eeb |
g_error_free (error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (connection);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
while (g_main_context_iteration (context, FALSE));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_context_unref (context);
|
|
Packit |
b00eeb |
g_main_loop_unref (thread_data->loop);
|
|
Packit |
b00eeb |
thread_data->loop = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_unlock (thread_data->mutex);
|
|
Packit |
b00eeb |
return thread_data;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_start:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Start the mock prompter. This is often used from the
|
|
Packit |
b00eeb |
* <literal>setup()</literal> function of tests.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Starts the mock prompter in an additional thread. Use the returned DBus bus
|
|
Packit |
b00eeb |
* name with gcr_system_prompt_open_for_prompter() to connect to this prompter.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: the bus name that the mock prompter is listening on
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
const gchar *
|
|
Packit |
b00eeb |
gcr_mock_prompter_start (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GError *error = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running == NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
running = g_new0 (ThreadData, 1);
|
|
Packit |
b00eeb |
running->mutex = g_new0 (GMutex, 1);
|
|
Packit |
b00eeb |
g_mutex_init (running->mutex);
|
|
Packit |
b00eeb |
running->start_cond = g_new0 (GCond, 1);
|
|
Packit |
b00eeb |
g_cond_init (running->start_cond);
|
|
Packit |
b00eeb |
g_queue_init (&running->responses);
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
running->thread = g_thread_new ("mock-prompter", mock_prompter_thread, running);
|
|
Packit |
b00eeb |
if (error != NULL)
|
|
Packit |
b00eeb |
g_error ("mock prompter couldn't start thread: %s", error->message);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_cond_wait (running->start_cond, running->mutex);
|
|
Packit |
b00eeb |
g_assert (running->loop);
|
|
Packit |
b00eeb |
g_assert (running->prompter);
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return g_dbus_connection_get_unique_name (running->connection);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_disconnect:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Disconnect the mock prompter
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_mock_prompter_disconnect (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GError *error = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
g_assert (running->connection);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_dbus_connection_close_sync (running->connection, NULL, &error);
|
|
Packit |
b00eeb |
if (error != NULL) {
|
|
Packit |
b00eeb |
g_critical ("disconnect connection close failed: %s", error->message);
|
|
Packit |
b00eeb |
g_error_free (error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_mock_prompter_stop:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Stop the mock prompter. This is often used from the
|
|
Packit |
b00eeb |
* <literal>teardown()</literal> function of tests.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_mock_prompter_stop (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
ThreadData *check;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (running != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_mutex_lock (running->mutex);
|
|
Packit |
b00eeb |
g_assert (running->loop != NULL);
|
|
Packit |
b00eeb |
g_main_loop_quit (running->loop);
|
|
Packit |
b00eeb |
g_mutex_unlock (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
check = g_thread_join (running->thread);
|
|
Packit |
b00eeb |
g_assert (check == running);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_queue_foreach (&running->responses, (GFunc)mock_response_free, NULL);
|
|
Packit |
b00eeb |
g_queue_clear (&running->responses);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_cond_clear (running->start_cond);
|
|
Packit |
b00eeb |
g_free (running->start_cond);
|
|
Packit |
b00eeb |
g_mutex_clear (running->mutex);
|
|
Packit |
b00eeb |
g_free (running->mutex);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_free (running);
|
|
Packit |
b00eeb |
running = NULL;
|
|
Packit |
b00eeb |
}
|