LCOV - code coverage report
Current view: top level - gcr - gcr-mock-prompter.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 388 466 83.3 %
Date: 2022-09-04 10:20:22 Functions: 40 44 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 83 159 52.2 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * gnome-keyring
       3                 :            :  *
       4                 :            :  * Copyright (C) 2011 Collabora Ltd.
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or modify
       7                 :            :  * it under the terms of the GNU Lesser General Public License as
       8                 :            :  * published by the Free Software Foundation; either version 2.1 of
       9                 :            :  * the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This program is distributed in the hope that it will be useful, but
      12                 :            :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Lesser General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU Lesser General Public
      17                 :            :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18                 :            :  *
      19                 :            :  * Author: Stef Walter <stfew@collabora.co.uk>
      20                 :            :  */
      21                 :            : 
      22                 :            : #include "config.h"
      23                 :            : 
      24                 :            : #include "gcr-mock-prompter.h"
      25                 :            : #include "gcr-prompt.h"
      26                 :            : 
      27                 :            : #include "egg/egg-error.h"
      28                 :            : 
      29                 :            : #include <gobject/gvaluecollector.h>
      30                 :            : 
      31                 :            : #include <string.h>
      32                 :            : 
      33                 :            : /**
      34                 :            :  * GcrMockPrompter:
      35                 :            :  *
      36                 :            :  * A mock [class@SystemPrompter] used for testing against.
      37                 :            :  *
      38                 :            :  * Use [func@MockPrompter.start] to start the mock prompter in another
      39                 :            :  * thread. The returned string is the dbus address of the mock prompter.
      40                 :            :  * You can pass this to [func@SystemPrompt.open] as the prompter bus name.
      41                 :            :  *
      42                 :            :  * Use the [func@MockPrompter.expect_confirm_ok] function and friends before
      43                 :            :  * prompting to verify that the prompts are displayed as expected, and to
      44                 :            :  * provide a response.
      45                 :            :  */
      46                 :            : 
      47                 :            : #define GCR_TYPE_MOCK_PROMPT (_gcr_mock_prompt_get_type ())
      48                 :        435 : G_DECLARE_FINAL_TYPE (GcrMockPrompt, _gcr_mock_prompt,
      49                 :            :                       GCR, MOCK_PROMPT,
      50                 :            :                       GObject)
      51                 :            : 
      52                 :            : enum {
      53                 :            :         PROP_0,
      54                 :            : 
      55                 :            :         PROP_TITLE,
      56                 :            :         PROP_MESSAGE,
      57                 :            :         PROP_DESCRIPTION,
      58                 :            :         PROP_WARNING,
      59                 :            :         PROP_PASSWORD_NEW,
      60                 :            :         PROP_PASSWORD_STRENGTH,
      61                 :            :         PROP_CHOICE_LABEL,
      62                 :            :         PROP_CHOICE_CHOSEN,
      63                 :            :         PROP_CALLER_WINDOW,
      64                 :            :         PROP_CONTINUE_LABEL,
      65                 :            :         PROP_CANCEL_LABEL,
      66                 :            : };
      67                 :            : 
      68                 :            : typedef struct _MockProperty {
      69                 :            :         const char *name;
      70                 :            :         GValue value;
      71                 :            : } MockProperty;
      72                 :            : 
      73                 :            : struct _GcrMockPrompt {
      74                 :            :         GObject parent;
      75                 :            :         GHashTable *properties;
      76                 :            :         gboolean disposed;
      77                 :            : };
      78                 :            : 
      79                 :            : typedef struct {
      80                 :            :         gboolean close;
      81                 :            :         gboolean proceed;
      82                 :            :         gchar *password;
      83                 :            :         GList *properties;
      84                 :            : } MockResponse;
      85                 :            : 
      86                 :            : typedef struct {
      87                 :            :         /* Owned by the calling thread */
      88                 :            :         GMutex *mutex;
      89                 :            :         GCond *start_cond;
      90                 :            :         GThread *thread;
      91                 :            : 
      92                 :            :         guint delay_msec;
      93                 :            :         GQueue responses;
      94                 :            : 
      95                 :            :         /* Owned by the prompter thread*/
      96                 :            :         GcrSystemPrompter *prompter;
      97                 :            :         GDBusConnection *connection;
      98                 :            :         GMainLoop *loop;
      99                 :            : } ThreadData;
     100                 :            : 
     101                 :            : static gint prompts_a_prompting = 0;
     102                 :            : static ThreadData *running = NULL;
     103                 :            : 
     104                 :            : static void    gcr_mock_prompt_iface     (GcrPromptInterface *iface);
     105                 :            : 
     106   [ +  +  +  -  :        466 : G_DEFINE_TYPE_WITH_CODE (GcrMockPrompt, _gcr_mock_prompt, G_TYPE_OBJECT,
                   +  + ]
     107                 :            :                          G_IMPLEMENT_INTERFACE (GCR_TYPE_PROMPT, gcr_mock_prompt_iface);
     108                 :            : );
     109                 :            : 
     110                 :            : static void
     111                 :        452 : mock_property_free (gpointer data)
     112                 :            : {
     113                 :        452 :         MockProperty *param = data;
     114                 :        452 :         g_value_unset (&param->value);
     115                 :        452 :         g_free (param);
     116                 :        452 : }
     117                 :            : 
     118                 :            : static void
     119                 :         14 : mock_response_free (gpointer data)
     120                 :            : {
     121                 :         14 :         MockResponse *response = data;
     122                 :            : 
     123         [ -  + ]:         14 :         if (response == NULL)
     124                 :          0 :                 return;
     125                 :            : 
     126                 :         14 :         g_free (response->password);
     127                 :         14 :         g_list_free_full (response->properties, mock_property_free);
     128                 :         14 :         g_free (response);
     129                 :            : }
     130                 :            : 
     131                 :            : static void
     132                 :        144 : blank_string_property (GHashTable *properties,
     133                 :            :                        const gchar *property)
     134                 :            : {
     135                 :            :         MockProperty *param;
     136                 :            : 
     137                 :        144 :         param = g_new0 (MockProperty, 1);
     138                 :        144 :         param->name = property;
     139                 :        144 :         g_value_init (&param->value, G_TYPE_STRING);
     140                 :        144 :         g_value_set_string (&param->value, "");
     141                 :        144 :         g_hash_table_insert (properties, (gpointer)param->name, param);
     142                 :        144 : }
     143                 :            : 
     144                 :            : 
     145                 :            : static void
     146                 :         36 : blank_boolean_property (GHashTable *properties,
     147                 :            :                         const gchar *property)
     148                 :            : {
     149                 :            :         MockProperty *param;
     150                 :            : 
     151                 :         36 :         param = g_new0 (MockProperty, 1);
     152                 :         36 :         param->name = property;
     153                 :         36 :         g_value_init (&param->value, G_TYPE_BOOLEAN);
     154                 :         36 :         g_value_set_boolean (&param->value, FALSE);
     155                 :         36 :         g_hash_table_insert (properties, (gpointer)param->name, param);
     156                 :         36 : }
     157                 :            : 
     158                 :            : static void
     159                 :         18 : blank_int_property (GHashTable *properties,
     160                 :            :                     const gchar *property)
     161                 :            : {
     162                 :            :         MockProperty *param;
     163                 :            : 
     164                 :         18 :         param = g_new0 (MockProperty, 1);
     165                 :         18 :         param->name = property;
     166                 :         18 :         g_value_init (&param->value, G_TYPE_INT);
     167                 :         18 :         g_value_set_int (&param->value, 0);
     168                 :         18 :         g_hash_table_insert (properties, (gpointer)param->name, param);
     169                 :         18 : }
     170                 :            : 
     171                 :            : static void
     172                 :         18 : _gcr_mock_prompt_init (GcrMockPrompt *self)
     173                 :            : {
     174                 :         18 :         g_atomic_int_add (&prompts_a_prompting, 1);
     175                 :            : 
     176                 :         18 :         self->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
     177                 :            :                                                   NULL, mock_property_free);
     178                 :            : 
     179                 :         18 :         blank_string_property (self->properties, "title");
     180                 :         18 :         blank_string_property (self->properties, "message");
     181                 :         18 :         blank_string_property (self->properties, "description");
     182                 :         18 :         blank_string_property (self->properties, "warning");
     183                 :         18 :         blank_string_property (self->properties, "choice-label");
     184                 :         18 :         blank_string_property (self->properties, "caller-window");
     185                 :         18 :         blank_string_property (self->properties, "continue-label");
     186                 :         18 :         blank_string_property (self->properties, "cancel-label");
     187                 :            : 
     188                 :         18 :         blank_boolean_property (self->properties, "choice-chosen");
     189                 :         18 :         blank_boolean_property (self->properties, "password-new");
     190                 :            : 
     191                 :         18 :         blank_int_property (self->properties, "password-strength");
     192                 :         18 : }
     193                 :            : 
     194                 :            : static void
     195                 :        259 : _gcr_mock_prompt_set_property (GObject *obj,
     196                 :            :                               guint prop_id,
     197                 :            :                               const GValue *value,
     198                 :            :                               GParamSpec *pspec)
     199                 :            : {
     200                 :        259 :         GcrMockPrompt *self = GCR_MOCK_PROMPT (obj);
     201                 :            :         MockProperty *param;
     202                 :            : 
     203         [ +  - ]:        259 :         switch (prop_id) {
     204                 :        259 :         case PROP_TITLE:
     205                 :            :         case PROP_MESSAGE:
     206                 :            :         case PROP_DESCRIPTION:
     207                 :            :         case PROP_WARNING:
     208                 :            :         case PROP_PASSWORD_NEW:
     209                 :            :         case PROP_CHOICE_LABEL:
     210                 :            :         case PROP_CHOICE_CHOSEN:
     211                 :            :         case PROP_CALLER_WINDOW:
     212                 :            :         case PROP_CONTINUE_LABEL:
     213                 :            :         case PROP_CANCEL_LABEL:
     214                 :        259 :                 param = g_new0 (MockProperty, 1);
     215                 :        259 :                 param->name = pspec->name;
     216                 :        259 :                 g_value_init (&param->value, pspec->value_type);
     217                 :        259 :                 g_value_copy (value, &param->value);
     218                 :        259 :                 g_hash_table_replace (self->properties, (gpointer)param->name, param);
     219                 :        259 :                 g_object_notify (G_OBJECT (self), param->name);
     220                 :        259 :                 break;
     221                 :          0 :         default:
     222                 :          0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     223                 :          0 :                 break;
     224                 :            :         }
     225                 :        259 : }
     226                 :            : 
     227                 :            : static void
     228                 :        112 : _gcr_mock_prompt_get_property (GObject *obj,
     229                 :            :                               guint prop_id,
     230                 :            :                               GValue *value,
     231                 :            :                               GParamSpec *pspec)
     232                 :            : {
     233                 :        112 :         GcrMockPrompt *self = GCR_MOCK_PROMPT (obj);
     234                 :            :         MockProperty *param;
     235                 :            : 
     236         [ +  - ]:        112 :         switch (prop_id) {
     237                 :        112 :         case PROP_TITLE:
     238                 :            :         case PROP_MESSAGE:
     239                 :            :         case PROP_DESCRIPTION:
     240                 :            :         case PROP_WARNING:
     241                 :            :         case PROP_PASSWORD_NEW:
     242                 :            :         case PROP_PASSWORD_STRENGTH:
     243                 :            :         case PROP_CHOICE_LABEL:
     244                 :            :         case PROP_CHOICE_CHOSEN:
     245                 :            :         case PROP_CALLER_WINDOW:
     246                 :            :         case PROP_CONTINUE_LABEL:
     247                 :            :         case PROP_CANCEL_LABEL:
     248                 :        112 :                 param = g_hash_table_lookup (self->properties, pspec->name);
     249         [ -  + ]:        112 :                 g_return_if_fail (param != NULL);
     250                 :        112 :                 g_value_copy (&param->value, value);
     251                 :        112 :                 break;
     252                 :          0 :         default:
     253                 :          0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     254                 :          0 :                 break;
     255                 :            :         }
     256                 :            : }
     257                 :            : 
     258                 :            : 
     259                 :            : static void
     260                 :         34 : _gcr_mock_prompt_dispose (GObject *obj)
     261                 :            : {
     262                 :         34 :         GcrMockPrompt *self = GCR_MOCK_PROMPT (obj);
     263                 :            : 
     264         [ +  + ]:         34 :         if (!self->disposed) {
     265                 :         18 :                 g_atomic_int_add (&prompts_a_prompting, -1);
     266                 :         18 :                 self->disposed = TRUE;
     267                 :            :         }
     268                 :            : 
     269                 :         34 :         G_OBJECT_CLASS (_gcr_mock_prompt_parent_class)->dispose (obj);
     270                 :         34 : }
     271                 :            : 
     272                 :            : static void
     273                 :         16 : _gcr_mock_prompt_finalize (GObject *obj)
     274                 :            : {
     275                 :         16 :         GcrMockPrompt *self = GCR_MOCK_PROMPT (obj);
     276                 :            : 
     277                 :         16 :         g_hash_table_destroy(self->properties);
     278                 :            : 
     279                 :         16 :         G_OBJECT_CLASS (_gcr_mock_prompt_parent_class)->finalize (obj);
     280                 :         16 : }
     281                 :            : 
     282                 :            : static gboolean
     283                 :         10 : value_equal (const GValue *a, const GValue *b)
     284                 :            : {
     285                 :         10 :         gboolean ret = FALSE;
     286                 :            : 
     287         [ -  + ]:         10 :         g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));
     288                 :            : 
     289   [ +  -  +  -  :         10 :         switch (G_VALUE_TYPE (a)) {
             -  -  -  +  
                      - ]
     290                 :          1 :         case G_TYPE_BOOLEAN:
     291                 :          1 :                 ret = (g_value_get_boolean (a) == g_value_get_boolean (b));
     292                 :          1 :                 break;
     293                 :          0 :         case G_TYPE_UCHAR:
     294                 :          0 :                 ret = (g_value_get_uchar (a) == g_value_get_uchar (b));
     295                 :          0 :                 break;
     296                 :          1 :         case G_TYPE_INT:
     297                 :          1 :                 ret = (g_value_get_int (a) == g_value_get_int (b));
     298                 :          1 :                 break;
     299                 :          0 :         case G_TYPE_UINT:
     300                 :          0 :                 ret = (g_value_get_uint (a) == g_value_get_uint (b));
     301                 :          0 :                 break;
     302                 :          0 :         case G_TYPE_INT64:
     303                 :          0 :                 ret = (g_value_get_int64 (a) == g_value_get_int64 (b));
     304                 :          0 :                 break;
     305                 :          0 :         case G_TYPE_UINT64:
     306                 :          0 :                 ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));
     307                 :          0 :                 break;
     308                 :          0 :         case G_TYPE_DOUBLE:
     309                 :          0 :                 ret = (g_value_get_double (a) == g_value_get_double (b));
     310                 :          0 :                 break;
     311                 :          8 :         case G_TYPE_STRING:
     312                 :          8 :                 ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);
     313                 :          8 :                 break;
     314                 :          0 :         default:
     315                 :          0 :                 g_critical ("no support for comparing of type %s", g_type_name (G_VALUE_TYPE (a)));
     316                 :          0 :                 break;
     317                 :            :         }
     318                 :            : 
     319                 :         10 :         return ret;
     320                 :            : }
     321                 :            : 
     322                 :            : static void
     323                 :         13 : prompt_set_or_check_properties (GcrMockPrompt *self,
     324                 :            :                                 GList *properties)
     325                 :            : {
     326                 :         13 :         GValue value = G_VALUE_INIT;
     327                 :            :         GObjectClass *object_class;
     328                 :            :         MockProperty *param;
     329                 :            :         GParamSpec *spec;
     330                 :            :         GList *l;
     331                 :            : 
     332                 :         13 :         object_class = G_OBJECT_GET_CLASS (self);
     333   [ +  -  +  + ]:         24 :         for (l = properties; l != NULL; l = g_list_next (l)) {
     334                 :         11 :                 param = l->data;
     335                 :            : 
     336                 :         11 :                 spec = g_object_class_find_property (object_class, param->name);
     337         [ -  + ]:         11 :                 g_assert (spec != NULL);
     338                 :            : 
     339                 :            :                 /* For these we set the value */
     340         [ +  + ]:         11 :                 if (g_str_equal (param->name, "choice-chosen")) {
     341                 :          1 :                         g_object_set_property (G_OBJECT (self), param->name, &param->value);
     342                 :            : 
     343                 :            :                 /* For others we check that the value is correct */
     344                 :            :                 } else {
     345                 :         10 :                         g_value_init (&value, G_VALUE_TYPE (&param->value));
     346                 :         10 :                         g_object_get_property (G_OBJECT (self), param->name, &value);
     347         [ -  + ]:         10 :                         if (!value_equal (&value, &param->value)) {
     348                 :          0 :                                 gchar *expected = g_strdup_value_contents (&param->value);
     349                 :          0 :                                 gchar *actual = g_strdup_value_contents (&value);
     350                 :          0 :                                 g_critical ("expected prompt property '%s' to be %s, but it "
     351                 :            :                                             "is instead %s", param->name, expected, actual);
     352                 :          0 :                                 g_free (expected);
     353                 :          0 :                                 g_free (actual);
     354                 :            :                         }
     355                 :         10 :                         g_value_unset (&value);
     356                 :            :                 }
     357                 :            :         }
     358                 :         13 : }
     359                 :            : 
     360                 :            : static void
     361                 :          1 : _gcr_mock_prompt_class_init (GcrMockPromptClass *klass)
     362                 :            : {
     363                 :          1 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     364                 :            : 
     365                 :          1 :         gobject_class->get_property = _gcr_mock_prompt_get_property;
     366                 :          1 :         gobject_class->set_property = _gcr_mock_prompt_set_property;
     367                 :          1 :         gobject_class->dispose = _gcr_mock_prompt_dispose;
     368                 :          1 :         gobject_class->finalize = _gcr_mock_prompt_finalize;
     369                 :            : 
     370                 :          1 :         g_object_class_override_property (gobject_class, PROP_TITLE, "title");
     371                 :          1 :         g_object_class_override_property (gobject_class, PROP_MESSAGE, "message");
     372                 :          1 :         g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
     373                 :          1 :         g_object_class_override_property (gobject_class, PROP_WARNING, "warning");
     374                 :          1 :         g_object_class_override_property (gobject_class, PROP_CALLER_WINDOW, "caller-window");
     375                 :          1 :         g_object_class_override_property (gobject_class, PROP_CHOICE_LABEL, "choice-label");
     376                 :          1 :         g_object_class_override_property (gobject_class, PROP_CHOICE_CHOSEN, "choice-chosen");
     377                 :          1 :         g_object_class_override_property (gobject_class, PROP_PASSWORD_NEW, "password-new");
     378                 :          1 :         g_object_class_override_property (gobject_class, PROP_PASSWORD_STRENGTH, "password-strength");
     379                 :          1 :         g_object_class_override_property (gobject_class, PROP_CONTINUE_LABEL, "continue-label");
     380                 :          1 :         g_object_class_override_property (gobject_class, PROP_CANCEL_LABEL, "cancel-label");
     381                 :          1 : }
     382                 :            : 
     383                 :            : static gboolean
     384                 :         11 : on_timeout_complete (gpointer data)
     385                 :            : {
     386                 :         11 :         GSimpleAsyncResult *res = data;
     387                 :         11 :         g_simple_async_result_complete (res);
     388                 :         11 :         return FALSE;
     389                 :            : }
     390                 :            : 
     391                 :            : static gboolean
     392                 :          1 : on_timeout_complete_and_close (gpointer data)
     393                 :            : {
     394                 :          1 :         GSimpleAsyncResult *res = data;
     395                 :          1 :         GcrPrompt *prompt = GCR_PROMPT (g_async_result_get_source_object (data));
     396                 :          1 :         g_simple_async_result_complete (res);
     397                 :          1 :         gcr_prompt_close (prompt);
     398                 :          1 :         g_object_unref (prompt);
     399                 :          1 :         return FALSE;
     400                 :            : }
     401                 :            : 
     402                 :            : static void
     403                 :         12 : destroy_unref_source (gpointer source)
     404                 :            : {
     405         [ -  + ]:         12 :         if (!g_source_is_destroyed (source))
     406                 :          0 :                 g_source_destroy (source);
     407                 :         12 :         g_source_unref (source);
     408                 :         12 : }
     409                 :            : 
     410                 :            : static void
     411                 :          7 : gcr_mock_prompt_confirm_async (GcrPrompt *prompt,
     412                 :            :                                GCancellable *cancellable,
     413                 :            :                                GAsyncReadyCallback callback,
     414                 :            :                                gpointer user_data)
     415                 :            : {
     416                 :          7 :         GcrMockPrompt *self = GCR_MOCK_PROMPT (prompt);
     417                 :          7 :         GSourceFunc complete_func = on_timeout_complete;
     418                 :            :         GSimpleAsyncResult *res;
     419                 :            :         MockResponse *response;
     420                 :            :         GSource *source;
     421                 :            :         guint delay_msec;
     422                 :            : 
     423                 :          7 :         g_mutex_lock (running->mutex);
     424                 :          7 :         delay_msec = running->delay_msec;
     425                 :          7 :         response = g_queue_pop_head (&running->responses);
     426                 :          7 :         g_mutex_unlock (running->mutex);
     427                 :            : 
     428                 :          7 :         res = g_simple_async_result_new (G_OBJECT (prompt), callback, user_data,
     429                 :            :                                          gcr_mock_prompt_confirm_async);
     430                 :            : 
     431         [ -  + ]:          7 :         if (response == NULL) {
     432                 :          0 :                 g_critical ("password prompt requested, but not expected");
     433                 :          0 :                 g_simple_async_result_set_op_res_gboolean (res, FALSE);
     434                 :            : 
     435         [ +  + ]:          7 :         } else if (response->close) {
     436                 :          1 :                 complete_func = on_timeout_complete_and_close;
     437                 :          1 :                 g_simple_async_result_set_op_res_gboolean (res, FALSE);
     438                 :            : 
     439         [ -  + ]:          6 :         } else if (response->password) {
     440                 :          0 :                 g_critical ("confirmation prompt requested, but password prompt expected");
     441                 :          0 :                 g_simple_async_result_set_op_res_gboolean (res, FALSE);
     442                 :            : 
     443                 :            :         } else {
     444                 :          6 :                 prompt_set_or_check_properties (self, response->properties);
     445                 :          6 :                 g_simple_async_result_set_op_res_gboolean (res, response->proceed);
     446                 :            :         }
     447                 :            : 
     448         [ -  + ]:          7 :         if (delay_msec > 0)
     449                 :          0 :                 source = g_timeout_source_new (delay_msec);
     450                 :            :         else
     451                 :          7 :                 source = g_idle_source_new ();
     452                 :            : 
     453                 :          7 :         g_source_set_callback (source, complete_func, g_object_ref (res), g_object_unref);
     454                 :          7 :         g_source_attach (source, g_main_context_get_thread_default ());
     455                 :          7 :         g_object_set_data_full (G_OBJECT (self), "delay-source", source, destroy_unref_source);
     456                 :            : 
     457                 :          7 :         mock_response_free (response);
     458                 :          7 :         g_object_unref (res);
     459                 :          7 : }
     460                 :            : 
     461                 :            : static GcrPromptReply
     462                 :          7 : gcr_mock_prompt_confirm_finish (GcrPrompt *prompt,
     463                 :            :                                 GAsyncResult *result,
     464                 :            :                                 GError **error)
     465                 :            : {
     466         [ -  + ]:          7 :         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (prompt),
     467                 :            :                               gcr_mock_prompt_confirm_async), GCR_PROMPT_REPLY_CANCEL);
     468                 :            : 
     469                 :          7 :         return g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (result)) ?
     470                 :          7 :                        GCR_PROMPT_REPLY_CONTINUE : GCR_PROMPT_REPLY_CANCEL;
     471                 :            : }
     472                 :            : 
     473                 :            : static void
     474                 :          6 : ensure_password_strength (GcrMockPrompt *self,
     475                 :            :                           const gchar *password)
     476                 :            : {
     477                 :            :         MockProperty *param;
     478                 :            :         gint strength;
     479                 :            : 
     480                 :          6 :         strength = strlen (password) > 0 ? 1 : 0;
     481                 :          6 :         param = g_new0 (MockProperty, 1);
     482                 :          6 :         param->name = "password-strength";
     483                 :          6 :         g_value_init (&param->value, G_TYPE_INT);
     484                 :          6 :         g_value_set_int (&param->value, strength);
     485                 :          6 :         g_hash_table_replace (self->properties, (gpointer)param->name, param);
     486                 :          6 :         g_object_notify (G_OBJECT (self), param->name);
     487                 :          6 : }
     488                 :            : 
     489                 :            : static void
     490                 :          7 : gcr_mock_prompt_password_async (GcrPrompt *prompt,
     491                 :            :                                 GCancellable *cancellable,
     492                 :            :                                 GAsyncReadyCallback callback,
     493                 :            :                                 gpointer user_data)
     494                 :            : {
     495                 :          7 :         GcrMockPrompt *self = GCR_MOCK_PROMPT (prompt);
     496                 :          7 :         GSourceFunc complete_func = on_timeout_complete;
     497                 :            :         GSimpleAsyncResult *res;
     498                 :            :         MockResponse *response;
     499                 :            :         GSource *source;
     500                 :            :         guint delay_msec;
     501                 :            : 
     502                 :          7 :         g_mutex_lock (running->mutex);
     503                 :          7 :         delay_msec = running->delay_msec;
     504                 :          7 :         response = g_queue_pop_head (&running->responses);
     505                 :          7 :         g_mutex_unlock (running->mutex);
     506                 :            : 
     507                 :          7 :         res = g_simple_async_result_new (G_OBJECT (prompt), callback, user_data,
     508                 :            :                                          gcr_mock_prompt_password_async);
     509                 :            : 
     510         [ -  + ]:          7 :         if (response == NULL) {
     511                 :          0 :                 g_critical ("password prompt requested, but not expected");
     512                 :          0 :                 g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
     513                 :            : 
     514         [ -  + ]:          7 :         } else if (response->close) {
     515                 :          0 :                 g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
     516                 :          0 :                 complete_func = on_timeout_complete_and_close;
     517                 :            : 
     518         [ -  + ]:          7 :         } else if (!response->password) {
     519                 :          0 :                 g_critical ("password prompt requested, but confirmation prompt expected");
     520                 :          0 :                 g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
     521                 :            : 
     522         [ +  + ]:          7 :         } else if (!response->proceed) {
     523                 :          1 :                 prompt_set_or_check_properties (self, response->properties);
     524                 :          1 :                 g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
     525                 :            : 
     526                 :            :         } else {
     527                 :          6 :                 ensure_password_strength (self, response->password);
     528                 :          6 :                 prompt_set_or_check_properties (self, response->properties);
     529                 :          6 :                 g_simple_async_result_set_op_res_gpointer (res, response->password, g_free);
     530                 :          6 :                 response->password = NULL;
     531                 :            :         }
     532                 :            : 
     533                 :          7 :         mock_response_free (response);
     534                 :            : 
     535         [ +  + ]:          7 :         if (delay_msec > 0)
     536                 :          2 :                 source = g_timeout_source_new (delay_msec);
     537                 :            :         else
     538                 :          5 :                 source = g_idle_source_new ();
     539                 :            : 
     540                 :          7 :         g_source_set_callback (source, complete_func, g_object_ref (res), g_object_unref);
     541                 :          7 :         g_source_attach (source, g_main_context_get_thread_default ());
     542                 :          7 :         g_object_set_data_full (G_OBJECT (self), "delay-source", source, destroy_unref_source);
     543                 :            : 
     544                 :          7 :         g_object_unref (res);
     545                 :          7 : }
     546                 :            : 
     547                 :            : 
     548                 :            : static const gchar *
     549                 :          5 : gcr_mock_prompt_password_finish (GcrPrompt *prompt,
     550                 :            :                                  GAsyncResult *result,
     551                 :            :                                  GError **error)
     552                 :            : {
     553         [ -  + ]:          5 :         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (prompt),
     554                 :            :                               gcr_mock_prompt_password_async), NULL);
     555                 :            : 
     556                 :          5 :         return g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
     557                 :            : 
     558                 :            : }
     559                 :            : 
     560                 :            : static void
     561                 :          1 : gcr_mock_prompt_iface (GcrPromptInterface *iface)
     562                 :            : {
     563                 :          1 :         iface->prompt_confirm_async = gcr_mock_prompt_confirm_async;
     564                 :          1 :         iface->prompt_confirm_finish = gcr_mock_prompt_confirm_finish;
     565                 :          1 :         iface->prompt_password_async = gcr_mock_prompt_password_async;
     566                 :          1 :         iface->prompt_password_finish = gcr_mock_prompt_password_finish;
     567                 :          1 : }
     568                 :            : 
     569                 :            : static GList *
     570                 :         11 : build_properties (GObjectClass *object_class,
     571                 :            :                   const gchar *first_property,
     572                 :            :                   va_list var_args)
     573                 :            : {
     574                 :         11 :         GList *result = NULL;
     575                 :            :         const gchar *name;
     576                 :            : 
     577                 :         11 :         name = first_property;
     578         [ +  + ]:         22 :         while (name) {
     579                 :         11 :                 GValue value = G_VALUE_INIT;
     580                 :            :                 MockProperty *parameter;
     581                 :            :                 GParamSpec *spec;
     582                 :         11 :                 gchar *error = NULL;
     583                 :            : 
     584                 :         11 :                 spec = g_object_class_find_property (object_class, name);
     585         [ -  + ]:         11 :                 if (spec == NULL) {
     586                 :          0 :                         g_warning ("prompt object class has no property named '%s'", name);
     587                 :          0 :                         break;
     588                 :            :                 }
     589                 :            : 
     590   [ -  +  -  - ]:         11 :                 if ((spec->flags & G_PARAM_CONSTRUCT_ONLY) && !(spec->flags & G_PARAM_READABLE)) {
     591                 :          0 :                         g_warning ("prompt property '%s' can't be set after construction", name);
     592                 :          0 :                         break;
     593                 :            :                 }
     594                 :            : 
     595   [ +  -  -  -  :         22 :                 G_VALUE_COLLECT_INIT (&value, spec->value_type, var_args, 0, &error);
             +  -  +  + ]
     596         [ -  + ]:         11 :                 if (error != NULL) {
     597                 :          0 :                         g_warning ("%s", error);
     598                 :          0 :                         g_free (error);
     599                 :          0 :                         g_value_unset (&value);
     600                 :          0 :                         break;
     601                 :            :                 }
     602                 :            : 
     603                 :         11 :                 parameter = g_new0 (MockProperty, 1);
     604                 :         11 :                 parameter->name = g_intern_string (name);
     605                 :         11 :                 memcpy (&parameter->value, &value, sizeof (value));
     606                 :         11 :                 result = g_list_prepend (result, parameter);
     607                 :            : 
     608                 :         11 :                 name = va_arg (var_args, gchar *);
     609                 :            :         }
     610                 :            : 
     611                 :         11 :         return result;
     612                 :            : }
     613                 :            : 
     614                 :            : /**
     615                 :            :  * gcr_mock_prompter_is_prompting:
     616                 :            :  *
     617                 :            :  * Check if the mock prompter is showing any prompts.
     618                 :            :  *
     619                 :            :  * Returns: whether prompting
     620                 :            :  */
     621                 :            : gboolean
     622                 :          0 : gcr_mock_prompter_is_prompting (void)
     623                 :            : {
     624                 :          0 :         return g_atomic_int_get (&prompts_a_prompting) > 0;
     625                 :            : }
     626                 :            : 
     627                 :            : /**
     628                 :            :  * gcr_mock_prompter_get_delay_msec:
     629                 :            :  *
     630                 :            :  * Get the delay in milliseconds before the mock prompter completes
     631                 :            :  * an expected prompt.
     632                 :            :  *
     633                 :            :  * Returns: the delay
     634                 :            :  */
     635                 :            : guint
     636                 :          0 : gcr_mock_prompter_get_delay_msec (void)
     637                 :            : {
     638                 :            :         guint delay_msec;
     639                 :            : 
     640         [ #  # ]:          0 :         g_assert (running != NULL);
     641                 :          0 :         g_mutex_lock (running->mutex);
     642                 :          0 :         delay_msec = running->delay_msec;
     643                 :          0 :         g_mutex_unlock (running->mutex);
     644                 :            : 
     645                 :          0 :         return delay_msec;
     646                 :            : }
     647                 :            : 
     648                 :            : /**
     649                 :            :  * gcr_mock_prompter_set_delay_msec:
     650                 :            :  * @delay_msec: prompt response delay in milliseconds
     651                 :            :  *
     652                 :            :  * Set the delay in milliseconds before the mock prompter completes
     653                 :            :  * an expected prompt.
     654                 :            :  */
     655                 :            : void
     656                 :          2 : gcr_mock_prompter_set_delay_msec (guint delay_msec)
     657                 :            : {
     658         [ -  + ]:          2 :         g_assert (running != NULL);
     659                 :          2 :         g_mutex_lock (running->mutex);
     660                 :          2 :         running->delay_msec = delay_msec;
     661                 :          2 :         g_mutex_unlock (running->mutex);
     662                 :          2 : }
     663                 :            : 
     664                 :            : /**
     665                 :            :  * gcr_mock_prompter_expect_confirm_ok:
     666                 :            :  * @first_property_name: the first property name in the argument list or %NULL
     667                 :            :  * @...: properties to expect
     668                 :            :  *
     669                 :            :  * Queue an expected response on the mock prompter.
     670                 :            :  *
     671                 :            :  * Expects a confirmation prompt, and then confirms that prompt by
     672                 :            :  * simulating a click on the ok button.
     673                 :            :  *
     674                 :            :  * Additional property pairs for the prompt can be added in the argument
     675                 :            :  * list, in the same way that you would with g_object_new().
     676                 :            :  *
     677                 :            :  * If the "choice-chosen" property is specified then that value will be
     678                 :            :  * set on the prompt as if the user had changed the value.
     679                 :            :  *
     680                 :            :  * All other properties will be checked against the prompt, and an error
     681                 :            :  * will occur if they do not match the value set on the prompt.
     682                 :            :  */
     683                 :            : void
     684                 :          5 : gcr_mock_prompter_expect_confirm_ok (const gchar *first_property_name,
     685                 :            :                                      ...)
     686                 :            : {
     687                 :            :         MockResponse *response;
     688                 :            :         gpointer klass;
     689                 :            :         va_list var_args;
     690                 :            : 
     691         [ -  + ]:          5 :         g_assert (running != NULL);
     692                 :            : 
     693                 :          5 :         g_mutex_lock (running->mutex);
     694                 :            : 
     695                 :          5 :         response = g_new0 (MockResponse, 1);
     696                 :          5 :         response->password = NULL;
     697                 :          5 :         response->proceed = TRUE;
     698                 :            : 
     699                 :          5 :         klass = g_type_class_ref (GCR_TYPE_MOCK_PROMPT);
     700                 :            : 
     701                 :          5 :         va_start (var_args, first_property_name);
     702                 :          5 :         response->properties = build_properties (G_OBJECT_CLASS (klass), first_property_name, var_args);
     703                 :          5 :         va_end (var_args);
     704                 :            : 
     705                 :          5 :         g_type_class_unref (klass);
     706                 :          5 :         g_queue_push_tail (&running->responses, response);
     707                 :          5 :         g_mutex_unlock (running->mutex);
     708                 :          5 : }
     709                 :            : 
     710                 :            : /**
     711                 :            :  * gcr_mock_prompter_expect_confirm_cancel:
     712                 :            :  *
     713                 :            :  * Queue an expected response on the mock prompter.
     714                 :            :  *
     715                 :            :  * Expects a confirmation prompt, and then cancels that prompt.
     716                 :            :  */
     717                 :            : void
     718                 :          1 : gcr_mock_prompter_expect_confirm_cancel (void)
     719                 :            : {
     720                 :            :         MockResponse *response;
     721                 :            : 
     722         [ -  + ]:          1 :         g_assert (running != NULL);
     723                 :            : 
     724                 :          1 :         g_mutex_lock (running->mutex);
     725                 :            : 
     726                 :          1 :         response = g_new0 (MockResponse, 1);
     727                 :          1 :         response->password = NULL;
     728                 :          1 :         response->proceed = FALSE;
     729                 :            : 
     730                 :          1 :         g_queue_push_tail (&running->responses, response);
     731                 :            : 
     732                 :          1 :         g_mutex_unlock (running->mutex);
     733                 :          1 : }
     734                 :            : 
     735                 :            : /**
     736                 :            :  * gcr_mock_prompter_expect_password_ok:
     737                 :            :  * @password: the password to return from the prompt
     738                 :            :  * @first_property_name: the first property name in the argument list or %NULL
     739                 :            :  * @...: properties to expect
     740                 :            :  *
     741                 :            :  * Queue an expected response on the mock prompter.
     742                 :            :  *
     743                 :            :  * Expects a password prompt, and returns @password as if the user had entered
     744                 :            :  * it and clicked the ok button.
     745                 :            :  *
     746                 :            :  * Additional property pairs for the prompt can be added in the argument
     747                 :            :  * list, in the same way that you would with g_object_new().
     748                 :            :  *
     749                 :            :  * If the "choice-chosen" property is specified then that value will be
     750                 :            :  * set on the prompt as if the user had changed the value.
     751                 :            :  *
     752                 :            :  * All other properties will be checked against the prompt, and an error
     753                 :            :  * will occur if they do not match the value set on the prompt.
     754                 :            :  */
     755                 :            : void
     756                 :          6 : gcr_mock_prompter_expect_password_ok (const gchar *password,
     757                 :            :                                       const gchar *first_property_name,
     758                 :            :                                       ...)
     759                 :            : {
     760                 :            :         MockResponse *response;
     761                 :            :         gpointer klass;
     762                 :            :         va_list var_args;
     763                 :            : 
     764         [ -  + ]:          6 :         g_assert (running != NULL);
     765         [ -  + ]:          6 :         g_assert (password != NULL);
     766                 :            : 
     767                 :          6 :         g_mutex_lock (running->mutex);
     768                 :            : 
     769                 :          6 :         response = g_new0 (MockResponse, 1);
     770                 :          6 :         response->password = g_strdup (password);
     771                 :          6 :         response->proceed = TRUE;
     772                 :            : 
     773                 :          6 :         klass = g_type_class_ref (GCR_TYPE_MOCK_PROMPT);
     774                 :            : 
     775                 :          6 :         va_start (var_args, first_property_name);
     776                 :          6 :         response->properties = build_properties (G_OBJECT_CLASS (klass), first_property_name, var_args);
     777                 :          6 :         va_end (var_args);
     778                 :            : 
     779                 :          6 :         g_type_class_unref (klass);
     780                 :          6 :         g_queue_push_tail (&running->responses, response);
     781                 :            : 
     782                 :          6 :         g_mutex_unlock (running->mutex);
     783                 :          6 : }
     784                 :            : 
     785                 :            : /**
     786                 :            :  * gcr_mock_prompter_expect_password_cancel:
     787                 :            :  *
     788                 :            :  * Queue an expected response on the mock prompter.
     789                 :            :  *
     790                 :            :  * Expects a password prompt, and then cancels that prompt.
     791                 :            :  */
     792                 :            : void
     793                 :          1 : gcr_mock_prompter_expect_password_cancel (void)
     794                 :            : {
     795                 :            :         MockResponse *response;
     796                 :            : 
     797         [ -  + ]:          1 :         g_assert (running != NULL);
     798                 :            : 
     799                 :          1 :         g_mutex_lock (running->mutex);
     800                 :            : 
     801                 :          1 :         response = g_new0 (MockResponse, 1);
     802                 :          1 :         response->password = g_strdup ("");
     803                 :          1 :         response->proceed = FALSE;
     804                 :            : 
     805                 :          1 :         g_queue_push_tail (&running->responses, response);
     806                 :            : 
     807                 :          1 :         g_mutex_unlock (running->mutex);
     808                 :          1 : }
     809                 :            : 
     810                 :            : /**
     811                 :            :  * gcr_mock_prompter_expect_close:
     812                 :            :  *
     813                 :            :  * Queue an expected response on the mock prompter.
     814                 :            :  *
     815                 :            :  * Expects any prompt, and closes the prompt when it gets it.
     816                 :            :  */
     817                 :            : void
     818                 :          1 : gcr_mock_prompter_expect_close (void)
     819                 :            : {
     820                 :            :         MockResponse *response;
     821                 :            : 
     822         [ -  + ]:          1 :         g_assert (running != NULL);
     823                 :            : 
     824                 :          1 :         g_mutex_lock (running->mutex);
     825                 :            : 
     826                 :          1 :         response = g_new0 (MockResponse, 1);
     827                 :          1 :         response->close = TRUE;
     828                 :            : 
     829                 :          1 :         g_queue_push_tail (&running->responses, response);
     830                 :            : 
     831                 :          1 :         g_mutex_unlock (running->mutex);
     832                 :          1 : }
     833                 :            : 
     834                 :            : /**
     835                 :            :  * gcr_mock_prompter_is_expecting:
     836                 :            :  *
     837                 :            :  * Check if the mock prompter is expecting a response. This will be %TRUE
     838                 :            :  * when one of the <literal>gcr_mock_prompter_expect_xxx<!-- -->()</literal>
     839                 :            :  * functions have been used to queue an expected prompt, but that prompt
     840                 :            :  * response has not be 'used' yet.
     841                 :            :  *
     842                 :            :  * Returns: whether expecting a prompt
     843                 :            :  */
     844                 :            : gboolean
     845                 :          0 : gcr_mock_prompter_is_expecting (void)
     846                 :            : {
     847                 :            :         gboolean expecting;
     848                 :            : 
     849         [ #  # ]:          0 :         g_assert (running != NULL);
     850                 :            : 
     851                 :          0 :         g_mutex_lock (running->mutex);
     852                 :            : 
     853                 :          0 :         expecting = !g_queue_is_empty (&running->responses);
     854                 :            : 
     855                 :          0 :         g_mutex_unlock (running->mutex);
     856                 :            : 
     857                 :          0 :         return expecting;
     858                 :            : }
     859                 :            : 
     860                 :            : static gboolean
     861                 :         18 : on_idle_signal_cond (gpointer user_data)
     862                 :            : {
     863                 :         18 :         GCond *cond = user_data;
     864                 :         18 :         g_cond_signal (cond);
     865                 :         18 :         return FALSE; /* Don't run again */
     866                 :            : }
     867                 :            : 
     868                 :            : /*
     869                 :            :  * These next few functions test the new-prompt signals of
     870                 :            :  * GcrSystemPrompter. They should probably be in tests, but
     871                 :            :  * don't fit there nicely.
     872                 :            :  */
     873                 :            : static GcrPrompt *
     874                 :          8 : on_new_prompt_skipped (GcrSystemPrompter *prompter,
     875                 :            :                        gpointer user_data)
     876                 :            : {
     877   [ -  +  +  -  :          8 :         g_return_val_if_fail (GCR_IS_SYSTEM_PROMPTER (prompter), NULL);
             +  -  -  + ]
     878                 :          8 :         return NULL;
     879                 :            : }
     880                 :            : 
     881                 :            : static GcrPrompt *
     882                 :          8 : on_new_prompt_creates (GcrSystemPrompter *prompter,
     883                 :            :                        gpointer user_data)
     884                 :            : {
     885   [ -  +  +  -  :          8 :         g_return_val_if_fail (GCR_IS_SYSTEM_PROMPTER (prompter), NULL);
             +  -  -  + ]
     886                 :          8 :         return g_object_new (GCR_TYPE_MOCK_PROMPT, NULL);
     887                 :            : }
     888                 :            : 
     889                 :            : static GcrPrompt *
     890                 :          0 : on_new_prompt_not_called (GcrSystemPrompter *prompter,
     891                 :            :                           gpointer user_data)
     892                 :            : {
     893   [ #  #  #  #  :          0 :         g_return_val_if_fail (GCR_IS_SYSTEM_PROMPTER (prompter), NULL);
             #  #  #  # ]
     894                 :          0 :         g_return_val_if_reached (NULL);
     895                 :            : }
     896                 :            : 
     897                 :            : static gpointer
     898                 :         18 : mock_prompter_thread (gpointer data)
     899                 :            : {
     900                 :         18 :         ThreadData *thread_data = data;
     901                 :         18 :         GDBusConnection *connection = NULL;
     902                 :            :         GMainContext *context;
     903                 :         18 :         GError *error = NULL;
     904                 :            :         GSource *idle;
     905                 :            :         gchar *address;
     906                 :            : 
     907                 :         18 :         g_mutex_lock (thread_data->mutex);
     908                 :         18 :         context = g_main_context_new ();
     909                 :         18 :         g_main_context_push_thread_default (context);
     910                 :            : 
     911                 :            :         /*
     912                 :            :          * Random choice between signals, and prompt-gtype style of creating
     913                 :            :          * GcrPrompt objects.
     914                 :            :          */
     915                 :            : 
     916         [ +  + ]:         18 :         if (g_random_boolean ()) {
     917                 :            :                 /* Allows GcrSystemPrompter to create the prompts directly */
     918                 :         10 :                 thread_data->prompter = gcr_system_prompter_new (GCR_SYSTEM_PROMPTER_SINGLE,
     919                 :            :                                                                  GCR_TYPE_MOCK_PROMPT);
     920                 :            : 
     921                 :            :         } else {
     922                 :            :                 /* Create the prompt objects in signal handler */
     923                 :          8 :                 thread_data->prompter = gcr_system_prompter_new (GCR_SYSTEM_PROMPTER_SINGLE, 0);
     924                 :          8 :                 g_signal_connect (thread_data->prompter, "new-prompt", G_CALLBACK (on_new_prompt_skipped), NULL);
     925                 :          8 :                 g_signal_connect (thread_data->prompter, "new-prompt", G_CALLBACK (on_new_prompt_creates), NULL);
     926                 :          8 :                 g_signal_connect (thread_data->prompter, "new-prompt", G_CALLBACK (on_new_prompt_not_called), NULL);
     927                 :            :         }
     928                 :            : 
     929                 :         18 :         address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, &error);
     930         [ +  - ]:         18 :         if (error == NULL) {
     931                 :         18 :                 connection = g_dbus_connection_new_for_address_sync (address,
     932                 :            :                                                                      G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
     933                 :            :                                                                      G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
     934                 :            :                                                                      NULL, NULL, &error);
     935         [ +  - ]:         18 :                 if (error == NULL) {
     936                 :         18 :                         thread_data->connection = connection;
     937                 :         18 :                         gcr_system_prompter_register (GCR_SYSTEM_PROMPTER (thread_data->prompter),
     938                 :            :                                                       connection);
     939                 :            :                 } else {
     940                 :          0 :                         g_critical ("couldn't create connection: %s", error->message);
     941                 :          0 :                         g_error_free (error);
     942                 :            :                 }
     943                 :            : 
     944                 :         18 :                 g_free (address);
     945                 :            :         }
     946                 :            : 
     947         [ -  + ]:         18 :         if (error != NULL) {
     948                 :          0 :                 g_critical ("mock prompter couldn't get session bus address: %s",
     949                 :            :                             egg_error_message (error));
     950                 :          0 :                 g_clear_error (&error);
     951                 :            :         }
     952                 :            : 
     953                 :         18 :         thread_data->loop = g_main_loop_new (context, FALSE);
     954                 :         18 :         g_mutex_unlock (thread_data->mutex);
     955                 :            : 
     956                 :         18 :         idle = g_idle_source_new ();
     957                 :         18 :         g_source_set_callback (idle, on_idle_signal_cond, thread_data->start_cond, NULL);
     958                 :         18 :         g_source_attach (idle, context);
     959                 :         18 :         g_source_unref (idle);
     960                 :            : 
     961                 :         18 :         g_main_loop_run (thread_data->loop);
     962                 :            : 
     963                 :         18 :         g_mutex_lock (thread_data->mutex);
     964                 :         18 :         g_main_context_pop_thread_default (context);
     965                 :            : 
     966                 :         18 :         gcr_system_prompter_unregister (thread_data->prompter, TRUE);
     967                 :         18 :         g_object_unref (thread_data->prompter);
     968                 :         18 :         thread_data->prompter = NULL;
     969                 :            : 
     970         [ +  - ]:         18 :         if (connection) {
     971                 :         18 :                 thread_data->connection = NULL;
     972                 :            : 
     973         [ +  + ]:         18 :                 if (!g_dbus_connection_is_closed (connection)) {
     974         [ -  + ]:         17 :                         if (!g_dbus_connection_flush_sync (connection, NULL, &error)) {
     975                 :          0 :                                 g_critical ("connection flush failed: %s", error->message);
     976                 :          0 :                                 g_error_free (error);
     977                 :            :                         }
     978         [ -  + ]:         17 :                         if (!g_dbus_connection_close_sync (connection, NULL, &error)) {
     979                 :          0 :                                 g_critical ("connection close failed: %s", error->message);
     980                 :          0 :                                 g_error_free (error);
     981                 :            :                         }
     982                 :            :                 }
     983                 :            : 
     984                 :         18 :                 g_object_unref (connection);
     985                 :            :         }
     986                 :            : 
     987         [ +  + ]:         40 :         while (g_main_context_iteration (context, FALSE));
     988                 :            : 
     989                 :         18 :         g_main_context_unref (context);
     990                 :         18 :         g_main_loop_unref (thread_data->loop);
     991                 :         18 :         thread_data->loop = NULL;
     992                 :            : 
     993                 :         18 :         g_mutex_unlock (thread_data->mutex);
     994                 :         18 :         return thread_data;
     995                 :            : }
     996                 :            : 
     997                 :            : /**
     998                 :            :  * gcr_mock_prompter_start:
     999                 :            :  *
    1000                 :            :  * Start the mock prompter. This is often used from the
    1001                 :            :  * <literal>setup<!-- -->()</literal> function of tests.
    1002                 :            :  *
    1003                 :            :  * Starts the mock prompter in an additional thread. Use the returned DBus bus
    1004                 :            :  * name with gcr_system_prompt_open_for_prompter() to connect to this prompter.
    1005                 :            :  *
    1006                 :            :  * Returns: the bus name that the mock prompter is listening on
    1007                 :            :  */
    1008                 :            : const gchar *
    1009                 :         18 : gcr_mock_prompter_start (void)
    1010                 :            : {
    1011                 :         18 :         GError *error = NULL;
    1012                 :            : 
    1013         [ -  + ]:         18 :         g_assert (running == NULL);
    1014                 :            : 
    1015                 :         18 :         running = g_new0 (ThreadData, 1);
    1016                 :         18 :         running->mutex = g_new0 (GMutex, 1);
    1017                 :         18 :         g_mutex_init (running->mutex);
    1018                 :         18 :         running->start_cond = g_new0 (GCond, 1);
    1019                 :         18 :         g_cond_init (running->start_cond);
    1020                 :         18 :         g_queue_init (&running->responses);
    1021                 :         18 :         g_mutex_lock (running->mutex);
    1022                 :            : 
    1023                 :         18 :         running->thread = g_thread_new ("mock-prompter", mock_prompter_thread, running);
    1024         [ -  + ]:         18 :         if (error != NULL)
    1025                 :          0 :                 g_error ("mock prompter couldn't start thread: %s", error->message);
    1026                 :            : 
    1027                 :         18 :         g_cond_wait (running->start_cond, running->mutex);
    1028         [ -  + ]:         18 :         g_assert (running->loop);
    1029         [ -  + ]:         18 :         g_assert (running->prompter);
    1030                 :         18 :         g_mutex_unlock (running->mutex);
    1031                 :            : 
    1032                 :         18 :         return g_dbus_connection_get_unique_name (running->connection);
    1033                 :            : }
    1034                 :            : 
    1035                 :            : /**
    1036                 :            :  * gcr_mock_prompter_disconnect:
    1037                 :            :  *
    1038                 :            :  * Disconnect the mock prompter
    1039                 :            :  */
    1040                 :            : void
    1041                 :          1 : gcr_mock_prompter_disconnect (void)
    1042                 :            : {
    1043                 :          1 :         GError *error = NULL;
    1044                 :            : 
    1045         [ -  + ]:          1 :         g_assert (running != NULL);
    1046         [ -  + ]:          1 :         g_assert (running->connection);
    1047                 :            : 
    1048                 :          1 :         g_dbus_connection_close_sync (running->connection, NULL, &error);
    1049         [ -  + ]:          1 :         if (error != NULL) {
    1050                 :          0 :                 g_critical ("disconnect connection close failed: %s", error->message);
    1051                 :          0 :                 g_error_free (error);
    1052                 :            :         }
    1053                 :          1 : }
    1054                 :            : 
    1055                 :            : /**
    1056                 :            :  * gcr_mock_prompter_stop:
    1057                 :            :  *
    1058                 :            :  * Stop the mock prompter. This is often used from the
    1059                 :            :  * <literal>teardown<!-- -->()</literal> function of tests.
    1060                 :            :  */
    1061                 :            : void
    1062                 :         18 : gcr_mock_prompter_stop (void)
    1063                 :            : {
    1064                 :            :         ThreadData *check;
    1065                 :            : 
    1066         [ -  + ]:         18 :         g_assert (running != NULL);
    1067                 :            : 
    1068                 :         18 :         g_mutex_lock (running->mutex);
    1069         [ -  + ]:         18 :         g_assert (running->loop != NULL);
    1070                 :         18 :         g_main_loop_quit (running->loop);
    1071                 :         18 :         g_mutex_unlock (running->mutex);
    1072                 :            : 
    1073                 :         18 :         check = g_thread_join (running->thread);
    1074         [ -  + ]:         18 :         g_assert (check == running);
    1075                 :            : 
    1076                 :         18 :         g_queue_foreach (&running->responses, (GFunc)mock_response_free, NULL);
    1077                 :         18 :         g_queue_clear (&running->responses);
    1078                 :            : 
    1079                 :         18 :         g_cond_clear (running->start_cond);
    1080                 :         18 :         g_free (running->start_cond);
    1081                 :         18 :         g_mutex_clear (running->mutex);
    1082                 :         18 :         g_free (running->mutex);
    1083                 :            : 
    1084                 :         18 :         g_free (running);
    1085                 :         18 :         running = NULL;
    1086                 :         18 : }

Generated by: LCOV version 1.14