LCOV - code coverage report
Current view: top level - glib/gio/tests - socket-service.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 232 232 100.0 %
Date: 2024-04-23 05:16:05 Functions: 23 23 100.0 %
Branches: 23 28 82.1 %

           Branch data     Line data    Source code
       1                 :            : /* GLib testing framework examples and tests
       2                 :            :  *
       3                 :            :  * Copyright 2014 Red Hat, Inc.
       4                 :            :  *
       5                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       6                 :            :  *
       7                 :            :  * This library is free software; you can redistribute it and/or
       8                 :            :  * modify it under the terms of the GNU Lesser General Public
       9                 :            :  * License as published by the Free Software Foundation; either
      10                 :            :  * version 2.1 of the License, or (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This library is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :            :  * Lesser General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU Lesser General Public
      18                 :            :  * License along with this library; if not, see
      19                 :            :  * <http://www.gnu.org/licenses/>.
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <gio/gio.h>
      23                 :            : 
      24                 :            : static void
      25                 :          2 : active_notify_cb (GSocketService *service,
      26                 :            :                   GParamSpec     *pspec,
      27                 :            :                   gpointer        data)
      28                 :            : {
      29                 :          2 :   gboolean *success = (gboolean *)data;
      30                 :            : 
      31         [ +  + ]:          2 :   if (g_socket_service_is_active (service))
      32                 :          1 :     *success = TRUE;
      33                 :          2 : }
      34                 :            : 
      35                 :            : static void
      36                 :          1 : connected_cb (GObject      *client,
      37                 :            :               GAsyncResult *result,
      38                 :            :               gpointer      user_data)
      39                 :            : {
      40                 :          1 :   GSocketService *service = G_SOCKET_SERVICE (user_data);
      41                 :            :   GSocketConnection *conn;
      42                 :          1 :   GError *error = NULL;
      43                 :            : 
      44                 :          1 :   g_assert_true (g_socket_service_is_active (service));
      45                 :            : 
      46                 :          1 :   conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), result, &error);
      47                 :          1 :   g_assert_no_error (error);
      48                 :          1 :   g_object_unref (conn);
      49                 :            : 
      50                 :          1 :   g_socket_service_stop (service);
      51                 :          1 :   g_assert_false (g_socket_service_is_active (service));
      52                 :          1 : }
      53                 :            : 
      54                 :            : static void
      55                 :          1 : test_start_stop (void)
      56                 :            : {
      57                 :          1 :   gboolean success = FALSE;
      58                 :            :   GInetAddress *iaddr;
      59                 :            :   GSocketAddress *saddr, *listening_addr;
      60                 :            :   GSocketService *service;
      61                 :          1 :   GError *error = NULL;
      62                 :            :   GSocketClient *client;
      63                 :            : 
      64                 :          1 :   iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
      65                 :          1 :   saddr = g_inet_socket_address_new (iaddr, 0);
      66                 :          1 :   g_object_unref (iaddr);
      67                 :            : 
      68                 :            :   /* instantiate with g_object_new so we can pass active = false */
      69                 :          1 :   service = g_object_new (G_TYPE_SOCKET_SERVICE, "active", FALSE, NULL);
      70                 :          1 :   g_assert_false (g_socket_service_is_active (service));
      71                 :            : 
      72                 :          1 :   g_signal_connect (service, "notify::active", G_CALLBACK (active_notify_cb), &success);
      73                 :            : 
      74                 :          1 :   g_socket_listener_add_address (G_SOCKET_LISTENER (service),
      75                 :            :                                  saddr,
      76                 :            :                                  G_SOCKET_TYPE_STREAM,
      77                 :            :                                  G_SOCKET_PROTOCOL_TCP,
      78                 :            :                                  NULL,
      79                 :            :                                  &listening_addr,
      80                 :            :                                  &error);
      81                 :          1 :   g_assert_no_error (error);
      82                 :          1 :   g_object_unref (saddr);
      83                 :            : 
      84                 :          1 :   client = g_socket_client_new ();
      85                 :          1 :   g_socket_client_connect_async (client,
      86                 :          1 :                                  G_SOCKET_CONNECTABLE (listening_addr),
      87                 :            :                                  NULL,
      88                 :            :                                  connected_cb, service);
      89                 :          1 :   g_object_unref (client);
      90                 :          1 :   g_object_unref (listening_addr);
      91                 :            : 
      92                 :          1 :   g_socket_service_start (service);
      93                 :          1 :   g_assert_true (g_socket_service_is_active (service));
      94                 :            : 
      95                 :            :   do
      96                 :          1 :     g_main_context_iteration (NULL, TRUE);
      97         [ -  + ]:          1 :   while (!success);
      98                 :            : 
      99                 :          1 :   g_object_unref (service);
     100                 :          1 : }
     101                 :            : 
     102                 :            : GMutex mutex_712570;
     103                 :            : GCond cond_712570;
     104                 :            : gboolean finalized;  /* (atomic) */
     105                 :            : 
     106                 :            : GType test_threaded_socket_service_get_type (void);
     107                 :            : typedef GThreadedSocketService TestThreadedSocketService;
     108                 :            : typedef GThreadedSocketServiceClass TestThreadedSocketServiceClass;
     109                 :            : 
     110   [ +  +  +  -  :          3 : G_DEFINE_TYPE (TestThreadedSocketService, test_threaded_socket_service, G_TYPE_THREADED_SOCKET_SERVICE)
                   +  - ]
     111                 :            : 
     112                 :            : static void
     113                 :          1 : test_threaded_socket_service_init (TestThreadedSocketService *service)
     114                 :            : {
     115                 :          1 : }
     116                 :            : 
     117                 :            : static void
     118                 :          1 : test_threaded_socket_service_finalize (GObject *object)
     119                 :            : {
     120                 :          1 :   G_OBJECT_CLASS (test_threaded_socket_service_parent_class)->finalize (object);
     121                 :            : 
     122                 :            :   /* Signal the main thread that finalization completed successfully
     123                 :            :    * rather than hanging.
     124                 :            :    */
     125                 :          1 :   g_atomic_int_set (&finalized, TRUE);
     126                 :          1 :   g_cond_signal (&cond_712570);
     127                 :          1 :   g_mutex_unlock (&mutex_712570);
     128                 :          1 : }
     129                 :            : 
     130                 :            : static void
     131                 :          1 : test_threaded_socket_service_class_init (TestThreadedSocketServiceClass *klass)
     132                 :            : {
     133                 :          1 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     134                 :            : 
     135                 :          1 :   object_class->finalize = test_threaded_socket_service_finalize;
     136                 :          1 : }
     137                 :            : 
     138                 :            : static gboolean
     139                 :          1 : connection_cb (GThreadedSocketService *service,
     140                 :            :                GSocketConnection      *connection,
     141                 :            :                GObject                *source_object,
     142                 :            :                gpointer                user_data)
     143                 :            : {
     144                 :          1 :   GMainLoop *loop = user_data;
     145                 :            : 
     146                 :            :   /* Since the connection attempt has come through to be handled, stop the main
     147                 :            :    * thread waiting for it; this causes the #GSocketService to be stopped. */
     148                 :          1 :   g_main_loop_quit (loop);
     149                 :            : 
     150                 :            :   /* Block until the main thread has dropped its ref to @service, so that we
     151                 :            :    * will drop the final ref from this thread.
     152                 :            :    */
     153                 :          1 :   g_mutex_lock (&mutex_712570);
     154                 :            : 
     155                 :            :   /* The service should now have 1 ref owned by the current "run"
     156                 :            :    * signal emission, and another added by GThreadedSocketService for
     157                 :            :    * this thread. Both will be dropped after we return.
     158                 :            :    */
     159                 :          1 :   g_assert_cmpint (G_OBJECT (service)->ref_count, ==, 2);
     160                 :            : 
     161                 :          1 :   return FALSE;
     162                 :            : }
     163                 :            : 
     164                 :            : static void
     165                 :          1 : client_connected_cb (GObject      *client,
     166                 :            :                      GAsyncResult *result,
     167                 :            :                      gpointer      user_data)
     168                 :            : {
     169                 :            :   GSocketConnection *conn;
     170                 :          1 :   GError *error = NULL;
     171                 :            : 
     172                 :          1 :   conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), result, &error);
     173                 :          1 :   g_assert_no_error (error);
     174                 :            : 
     175                 :          1 :   g_object_unref (conn);
     176                 :          1 : }
     177                 :            : 
     178                 :            : static void
     179                 :          1 : test_threaded_712570 (void)
     180                 :            : {
     181                 :            :   GSocketService *service;
     182                 :            :   GSocketAddress *addr, *listening_addr;
     183                 :            :   GMainLoop *loop;
     184                 :            :   GSocketClient *client;
     185                 :          1 :   GError *error = NULL;
     186                 :            : 
     187                 :          1 :   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=712570");
     188                 :            : 
     189                 :          1 :   g_mutex_lock (&mutex_712570);
     190                 :            : 
     191                 :          1 :   service = g_object_new (test_threaded_socket_service_get_type (), NULL);
     192                 :            : 
     193                 :          1 :   addr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
     194                 :          1 :   g_socket_listener_add_address (G_SOCKET_LISTENER (service),
     195                 :            :                                  addr,
     196                 :            :                                  G_SOCKET_TYPE_STREAM,
     197                 :            :                                  G_SOCKET_PROTOCOL_TCP,
     198                 :            :                                  NULL,
     199                 :            :                                  &listening_addr,
     200                 :            :                                  &error);
     201                 :          1 :   g_assert_no_error (error);
     202                 :          1 :   g_object_unref (addr);
     203                 :            : 
     204                 :          1 :   loop = g_main_loop_new (NULL, FALSE);
     205                 :          1 :   g_signal_connect (service, "run", G_CALLBACK (connection_cb), loop);
     206                 :            : 
     207                 :          1 :   client = g_socket_client_new ();
     208                 :          1 :   g_socket_client_connect_async (client,
     209                 :          1 :                                  G_SOCKET_CONNECTABLE (listening_addr),
     210                 :            :                                  NULL,
     211                 :            :                                  client_connected_cb, loop);
     212                 :          1 :   g_object_unref (client);
     213                 :          1 :   g_object_unref (listening_addr);
     214                 :            : 
     215                 :          1 :   g_main_loop_run (loop);
     216                 :          1 :   g_main_loop_unref (loop);
     217                 :            : 
     218                 :            :   /* Stop the service and then wait for it to asynchronously cancel
     219                 :            :    * its outstanding accept() call (and drop the associated ref).
     220                 :            :    * At least one main context iteration is required in some circumstances
     221                 :            :    * to ensure that the cancellation actually happens.
     222                 :            :    */
     223                 :          1 :   g_socket_service_stop (G_SOCKET_SERVICE (service));
     224                 :          1 :   g_assert_false (g_socket_service_is_active (G_SOCKET_SERVICE (service)));
     225                 :            : 
     226                 :            :   do
     227                 :          2 :     g_main_context_iteration (NULL, TRUE);
     228         [ +  + ]:          2 :   while (G_OBJECT (service)->ref_count > 3);
     229                 :            : 
     230                 :            :   /* Wait some more iterations, as #GTask results are deferred to the next
     231                 :            :    * #GMainContext iteration, and propagation of a #GTask result takes an
     232                 :            :    * additional ref on the source object. */
     233                 :          1 :   g_main_context_iteration (NULL, FALSE);
     234                 :            : 
     235                 :            :   /* Drop our ref, then unlock the mutex and wait for the service to be
     236                 :            :    * finalized. (Without the fix for 712570 it would hang forever here.)
     237                 :            :    */
     238                 :          1 :   g_object_unref (service);
     239                 :            : 
     240         [ +  + ]:          2 :   while (!g_atomic_int_get (&finalized))
     241                 :          1 :     g_cond_wait (&cond_712570, &mutex_712570);
     242                 :          1 :   g_mutex_unlock (&mutex_712570);
     243                 :          1 : }
     244                 :            : 
     245                 :            : static void
     246                 :          4 : closed_read_write_async_cb (GSocketConnection *conn,
     247                 :            :                             GAsyncResult      *result,
     248                 :            :                             gpointer           user_data)
     249                 :            : {
     250                 :          4 :   GError *error = NULL;
     251                 :            :   gboolean res;
     252                 :            : 
     253                 :          4 :   res = g_io_stream_close_finish (G_IO_STREAM (conn), result, &error);
     254                 :          4 :   g_assert_no_error (error);
     255                 :          4 :   g_assert_true (res);
     256                 :          4 : }
     257                 :            : 
     258                 :            : typedef struct {
     259                 :            :   GSocketConnection *conn;
     260                 :            :   guint8 *data;
     261                 :            : } WriteAsyncData;
     262                 :            : 
     263                 :            : static void
     264                 :          1 : written_read_write_async_cb (GOutputStream *ostream,
     265                 :            :                              GAsyncResult  *result,
     266                 :            :                              gpointer       user_data)
     267                 :            : {
     268                 :          1 :   WriteAsyncData *data = user_data;
     269                 :          1 :   GError *error = NULL;
     270                 :            :   gboolean res;
     271                 :            :   gsize bytes_written;
     272                 :            :   GSocketConnection *conn;
     273                 :            : 
     274                 :          1 :   conn = data->conn;
     275                 :            : 
     276                 :          1 :   g_free (data->data);
     277                 :          1 :   g_free (data);
     278                 :            : 
     279                 :          1 :   res = g_output_stream_write_all_finish (ostream, result, &bytes_written, &error);
     280                 :          1 :   g_assert_no_error (error);
     281                 :          1 :   g_assert_true (res);
     282                 :          1 :   g_assert_cmpuint (bytes_written, ==, 20);
     283                 :            : 
     284                 :          1 :   g_io_stream_close_async (G_IO_STREAM (conn),
     285                 :            :                            G_PRIORITY_DEFAULT,
     286                 :            :                            NULL,
     287                 :            :                            (GAsyncReadyCallback) closed_read_write_async_cb,
     288                 :            :                            NULL);
     289                 :          1 :   g_object_unref (conn);
     290                 :          1 : }
     291                 :            : 
     292                 :            : static void
     293                 :          1 : connected_read_write_async_cb (GObject      *client,
     294                 :            :                                GAsyncResult *result,
     295                 :            :                                gpointer      user_data)
     296                 :            : {
     297                 :            :   GSocketConnection *conn;
     298                 :            :   GOutputStream *ostream;
     299                 :          1 :   GError *error = NULL;
     300                 :            :   WriteAsyncData *data;
     301                 :            :   gsize i;
     302                 :          1 :   GSocketConnection **sconn = user_data;
     303                 :            : 
     304                 :          1 :   conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), result, &error);
     305                 :          1 :   g_assert_no_error (error);
     306                 :          1 :   g_assert_nonnull (conn);
     307                 :            : 
     308                 :          1 :   ostream = g_io_stream_get_output_stream (G_IO_STREAM (conn));
     309                 :            : 
     310                 :          1 :   data = g_new0 (WriteAsyncData, 1);
     311                 :          1 :   data->conn = conn;
     312                 :          1 :   data->data = g_new0 (guint8, 20);
     313         [ +  + ]:         21 :   for (i = 0; i < 20; i++)
     314                 :         20 :     data->data[i] = i;
     315                 :            : 
     316                 :          1 :   g_output_stream_write_all_async (ostream,
     317                 :          1 :                                    data->data,
     318                 :            :                                    20,
     319                 :            :                                    G_PRIORITY_DEFAULT,
     320                 :            :                                    NULL,
     321                 :            :                                    (GAsyncReadyCallback) written_read_write_async_cb,
     322                 :            :                                    data /* stolen */);
     323                 :            : 
     324                 :          1 :   *sconn = g_object_ref (conn);
     325                 :          1 : }
     326                 :            : 
     327                 :            : typedef struct {
     328                 :            :   GSocketConnection *conn;
     329                 :            :   GOutputVector *vectors;
     330                 :            :   guint n_vectors;
     331                 :            :   guint8 *data;
     332                 :            : } WritevAsyncData;
     333                 :            : 
     334                 :            : static void
     335                 :          1 : writtenv_read_write_async_cb (GOutputStream *ostream,
     336                 :            :                               GAsyncResult  *result,
     337                 :            :                               gpointer       user_data)
     338                 :            : {
     339                 :          1 :   WritevAsyncData *data = user_data;
     340                 :          1 :   GError *error = NULL;
     341                 :            :   gboolean res;
     342                 :            :   gsize bytes_written;
     343                 :            :   GSocketConnection *conn;
     344                 :            : 
     345                 :          1 :   conn = data->conn;
     346                 :          1 :   g_free (data->data);
     347                 :          1 :   g_free (data->vectors);
     348                 :          1 :   g_free (data);
     349                 :            : 
     350                 :          1 :   res = g_output_stream_writev_all_finish (ostream, result, &bytes_written, &error);
     351                 :          1 :   g_assert_no_error (error);
     352                 :          1 :   g_assert_true (res);
     353                 :          1 :   g_assert_cmpuint (bytes_written, ==, 20);
     354                 :            : 
     355                 :          1 :   g_io_stream_close_async (G_IO_STREAM (conn),
     356                 :            :                            G_PRIORITY_DEFAULT,
     357                 :            :                            NULL,
     358                 :            :                            (GAsyncReadyCallback) closed_read_write_async_cb,
     359                 :            :                            NULL);
     360                 :          1 :   g_object_unref (conn);
     361                 :          1 : }
     362                 :            : 
     363                 :            : static void
     364                 :          1 : connected_read_writev_async_cb (GObject      *client,
     365                 :            :                                GAsyncResult *result,
     366                 :            :                                gpointer      user_data)
     367                 :            : {
     368                 :            :   GSocketConnection *conn;
     369                 :            :   GOutputStream *ostream;
     370                 :          1 :   GError *error = NULL;
     371                 :            :   WritevAsyncData *data;
     372                 :            :   gsize i;
     373                 :          1 :   GSocketConnection **sconn = user_data;
     374                 :            : 
     375                 :          1 :   conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), result, &error);
     376                 :          1 :   g_assert_no_error (error);
     377                 :          1 :   g_assert_nonnull (conn);
     378                 :            : 
     379                 :          1 :   ostream = g_io_stream_get_output_stream (G_IO_STREAM (conn));
     380                 :            : 
     381                 :          1 :   data = g_new0 (WritevAsyncData, 1);
     382                 :          1 :   data->conn = conn;
     383                 :          1 :   data->vectors = g_new0 (GOutputVector, 3);
     384                 :          1 :   data->n_vectors = 3;
     385                 :          1 :   data->data = g_new0 (guint8, 20);
     386         [ +  + ]:         21 :   for (i = 0; i < 20; i++)
     387                 :         20 :     data->data[i] = i;
     388                 :            : 
     389                 :          1 :   data->vectors[0].buffer = data->data;
     390                 :          1 :   data->vectors[0].size = 5;
     391                 :          1 :   data->vectors[1].buffer = data->data + 5;
     392                 :          1 :   data->vectors[1].size = 10;
     393                 :          1 :   data->vectors[2].buffer = data->data + 15;
     394                 :          1 :   data->vectors[2].size = 5;
     395                 :            : 
     396                 :          1 :   g_output_stream_writev_all_async (ostream,
     397                 :            :                                     data->vectors,
     398                 :          1 :                                     data->n_vectors,
     399                 :            :                                     G_PRIORITY_DEFAULT,
     400                 :            :                                     NULL,
     401                 :            :                                     (GAsyncReadyCallback) writtenv_read_write_async_cb,
     402                 :            :                                     data /* stolen */);
     403                 :            : 
     404                 :          1 :   *sconn = g_object_ref (conn);
     405                 :          1 : }
     406                 :            : 
     407                 :            : typedef struct {
     408                 :            :   GSocketConnection *conn;
     409                 :            :   guint8 *data;
     410                 :            : } ReadAsyncData;
     411                 :            : 
     412                 :            : static void
     413                 :          2 : read_read_write_async_cb (GInputStream *istream,
     414                 :            :                           GAsyncResult *result,
     415                 :            :                           gpointer      user_data)
     416                 :            : {
     417                 :          2 :   ReadAsyncData *data = user_data;
     418                 :          2 :   GError *error = NULL;
     419                 :            :   gboolean res;
     420                 :            :   gsize bytes_read;
     421                 :            :   GSocketConnection *conn;
     422                 :          2 :   const guint8 expected_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
     423                 :            : 
     424                 :          2 :   res = g_input_stream_read_all_finish (istream, result, &bytes_read, &error);
     425                 :          2 :   g_assert_no_error (error);
     426                 :          2 :   g_assert_true (res);
     427                 :            : 
     428                 :          2 :   g_assert_cmpmem (expected_data, sizeof expected_data, data->data, bytes_read);
     429                 :            : 
     430                 :          2 :   conn = data->conn;
     431                 :          2 :   g_object_set_data (G_OBJECT (conn), "test-data-read", GINT_TO_POINTER (TRUE));
     432                 :            : 
     433                 :          2 :   g_free (data->data);
     434                 :          2 :   g_free (data);
     435                 :            : 
     436                 :          2 :   g_io_stream_close_async (G_IO_STREAM (conn),
     437                 :            :                            G_PRIORITY_DEFAULT,
     438                 :            :                            NULL,
     439                 :            :                            (GAsyncReadyCallback) closed_read_write_async_cb,
     440                 :            :                            NULL);
     441                 :          2 :   g_object_unref (conn);
     442                 :          2 : }
     443                 :            : 
     444                 :            : static void
     445                 :          2 : incoming_read_write_async_cb (GSocketService    *service,
     446                 :            :                               GSocketConnection *conn,
     447                 :            :                               GObject           *source_object,
     448                 :            :                               gpointer           user_data)
     449                 :            : {
     450                 :            :   ReadAsyncData *data;
     451                 :          2 :   GSocketConnection **cconn = user_data;
     452                 :            :   GInputStream *istream;
     453                 :            : 
     454                 :          2 :   istream = g_io_stream_get_input_stream (G_IO_STREAM (conn));
     455                 :            : 
     456                 :          2 :   data = g_new0 (ReadAsyncData, 1);
     457                 :          2 :   data->conn = g_object_ref (conn);
     458                 :          2 :   data->data = g_new0 (guint8, 20);
     459                 :            : 
     460                 :          2 :   g_input_stream_read_all_async (istream,
     461                 :          2 :                                  data->data,
     462                 :            :                                  20,
     463                 :            :                                  G_PRIORITY_DEFAULT,
     464                 :            :                                  NULL,
     465                 :            :                                  (GAsyncReadyCallback) read_read_write_async_cb,
     466                 :            :                                  data /* stolen */);
     467                 :            : 
     468                 :          2 :   *cconn = g_object_ref (conn);
     469                 :          2 : }
     470                 :            : 
     471                 :            : static void
     472                 :          2 : test_read_write_async_internal (gboolean writev)
     473                 :            : {
     474                 :            :   GInetAddress *iaddr;
     475                 :            :   GSocketAddress *saddr, *listening_addr;
     476                 :            :   GSocketService *service;
     477                 :          2 :   GError *error = NULL;
     478                 :            :   GSocketClient *client;
     479                 :          2 :   GSocketConnection *sconn = NULL, *cconn = NULL;
     480                 :            : 
     481                 :          2 :   iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
     482                 :          2 :   saddr = g_inet_socket_address_new (iaddr, 0);
     483                 :          2 :   g_object_unref (iaddr);
     484                 :            : 
     485                 :          2 :   service = g_socket_service_new ();
     486                 :            : 
     487                 :          2 :   g_socket_listener_add_address (G_SOCKET_LISTENER (service),
     488                 :            :                                  saddr,
     489                 :            :                                  G_SOCKET_TYPE_STREAM,
     490                 :            :                                  G_SOCKET_PROTOCOL_TCP,
     491                 :            :                                  NULL,
     492                 :            :                                  &listening_addr,
     493                 :            :                                  &error);
     494                 :          2 :   g_assert_no_error (error);
     495                 :          2 :   g_object_unref (saddr);
     496                 :            : 
     497                 :          2 :   g_signal_connect (service, "incoming", G_CALLBACK (incoming_read_write_async_cb), &sconn);
     498                 :            : 
     499                 :          2 :   client = g_socket_client_new ();
     500                 :            : 
     501         [ +  + ]:          2 :   if (writev)
     502                 :          1 :     g_socket_client_connect_async (client,
     503                 :          1 :                                    G_SOCKET_CONNECTABLE (listening_addr),
     504                 :            :                                    NULL,
     505                 :            :                                    connected_read_writev_async_cb,
     506                 :            :                                    &cconn);
     507                 :            :   else
     508                 :          1 :     g_socket_client_connect_async (client,
     509                 :          1 :                                    G_SOCKET_CONNECTABLE (listening_addr),
     510                 :            :                                    NULL,
     511                 :            :                                    connected_read_write_async_cb,
     512                 :            :                                    &cconn);
     513                 :            : 
     514                 :          2 :   g_object_unref (client);
     515                 :          2 :   g_object_unref (listening_addr);
     516                 :            : 
     517                 :          2 :   g_socket_service_start (service);
     518                 :          2 :   g_assert_true (g_socket_service_is_active (service));
     519                 :            : 
     520                 :            :   do
     521                 :            :     {
     522                 :         10 :       g_main_context_iteration (NULL, TRUE);
     523                 :            :     }
     524   [ -  +  +  + ]:         12 :   while (!sconn || !cconn ||
     525   [ +  +  -  + ]:         18 :          !g_io_stream_is_closed (G_IO_STREAM (sconn)) ||
     526                 :          2 :          !g_io_stream_is_closed (G_IO_STREAM (cconn)));
     527                 :            : 
     528                 :          2 :   g_assert_true (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (sconn), "test-data-read")));
     529                 :            : 
     530                 :          2 :   g_object_unref (sconn);
     531                 :          2 :   g_object_unref (cconn);
     532                 :          2 :   g_object_unref (service);
     533                 :          2 : }
     534                 :            : 
     535                 :            : /* Test if connecting to a socket service and asynchronously writing data on
     536                 :            :  * one side followed by reading the same data on the other side of the
     537                 :            :  * connection works correctly
     538                 :            :  */
     539                 :            : static void
     540                 :          1 : test_read_write_async (void)
     541                 :            : {
     542                 :          1 :   test_read_write_async_internal (FALSE);
     543                 :          1 : }
     544                 :            : 
     545                 :            : /* Test if connecting to a socket service and asynchronously writing data on
     546                 :            :  * one side followed by reading the same data on the other side of the
     547                 :            :  * connection works correctly. This uses writev() instead of normal write().
     548                 :            :  */
     549                 :            : static void
     550                 :          1 : test_read_writev_async (void)
     551                 :            : {
     552                 :          1 :   test_read_write_async_internal (TRUE);
     553                 :          1 : }
     554                 :            : 
     555                 :            : 
     556                 :            : int
     557                 :          1 : main (int   argc,
     558                 :            :       char *argv[])
     559                 :            : {
     560                 :          1 :   g_test_init (&argc, &argv, NULL);
     561                 :            : 
     562                 :          1 :   g_test_add_func ("/socket-service/start-stop", test_start_stop);
     563                 :          1 :   g_test_add_func ("/socket-service/threaded/712570", test_threaded_712570);
     564                 :          1 :   g_test_add_func ("/socket-service/read_write_async", test_read_write_async);
     565                 :          1 :   g_test_add_func ("/socket-service/read_writev_async", test_read_writev_async);
     566                 :            : 
     567                 :          1 :   return g_test_run();
     568                 :            : }

Generated by: LCOV version 1.14