LCOV - code coverage report
Current view: top level - glib/gio/tests - gdbus-overflow.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 0 73 0.0 %
Date: 2024-04-23 05:16:05 Functions: 0 4 0.0 %
Branches: 0 12 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* GLib testing framework examples and tests
       2                 :            :  *
       3                 :            :  * Copyright (C) 2008-2010 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
      18                 :            :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19                 :            :  *
      20                 :            :  * Author: David Zeuthen <davidz@redhat.com>
      21                 :            :  */
      22                 :            : 
      23                 :            : #include "config.h"
      24                 :            : 
      25                 :            : #include <gio/gio.h>
      26                 :            : #include <unistd.h>
      27                 :            : #include <string.h>
      28                 :            : 
      29                 :            : /* for open(2) */
      30                 :            : #include <sys/types.h>
      31                 :            : #include <sys/stat.h>
      32                 :            : #include <fcntl.h>
      33                 :            : #include <string.h>
      34                 :            : 
      35                 :            : /* for g_unlink() */
      36                 :            : #include <glib/gstdio.h>
      37                 :            : 
      38                 :            : #include <gio/gnetworking.h>
      39                 :            : #include <gio/gunixsocketaddress.h>
      40                 :            : #include <gio/gunixfdlist.h>
      41                 :            : 
      42                 :            : /* used in test_overflow */
      43                 :            : #ifdef G_OS_UNIX
      44                 :            : #include <gio/gunixconnection.h>
      45                 :            : #include <errno.h>
      46                 :            : #endif
      47                 :            : 
      48                 :            : #ifdef G_OS_UNIX
      49                 :            : static gboolean is_unix = TRUE;
      50                 :            : #else
      51                 :            : static gboolean is_unix = FALSE;
      52                 :            : #endif
      53                 :            : 
      54                 :            : static gchar *tmp_address = NULL;
      55                 :            : static gchar *test_guid = NULL;
      56                 :            : static GMainLoop *loop = NULL;
      57                 :            : 
      58                 :            : static const gchar *test_interface_introspection_xml =
      59                 :            :   "<node>"
      60                 :            :   "  <interface name='org.gtk.GDBus.PeerTestInterface'>"
      61                 :            :   "    <method name='HelloPeer'>"
      62                 :            :   "      <arg type='s' name='greeting' direction='in'/>"
      63                 :            :   "      <arg type='s' name='response' direction='out'/>"
      64                 :            :   "    </method>"
      65                 :            :   "    <method name='EmitSignal'/>"
      66                 :            :   "    <method name='EmitSignalWithNameSet'/>"
      67                 :            :   "    <method name='OpenFile'>"
      68                 :            :   "      <arg type='s' name='path' direction='in'/>"
      69                 :            :   "    </method>"
      70                 :            :   "    <signal name='PeerSignal'>"
      71                 :            :   "      <arg type='s' name='a_string'/>"
      72                 :            :   "    </signal>"
      73                 :            :   "    <property type='s' name='PeerProperty' access='read'/>"
      74                 :            :   "  </interface>"
      75                 :            :   "</node>";
      76                 :            : static GDBusInterfaceInfo *test_interface_introspection_data = NULL;
      77                 :            : 
      78                 :            : 
      79                 :            : #ifdef G_OS_UNIX
      80                 :            : 
      81                 :            : /* Chosen to be big enough to overflow the socket buffer */
      82                 :            : #define OVERFLOW_NUM_SIGNALS 5000
      83                 :            : #define OVERFLOW_TIMEOUT_SEC 10
      84                 :            : 
      85                 :            : static GDBusMessage *
      86                 :          0 : overflow_filter_func (GDBusConnection *connection,
      87                 :            :                       GDBusMessage    *message,
      88                 :            :                       gboolean         incoming,
      89                 :            :                       gpointer         user_data)
      90                 :            : {
      91                 :          0 :   gint *counter = user_data;  /* (atomic) */
      92                 :          0 :   g_atomic_int_inc (counter);
      93                 :          0 :   return message;
      94                 :            : }
      95                 :            : 
      96                 :            : static gboolean
      97                 :          0 : overflow_on_500ms_later_func (gpointer user_data)
      98                 :            : {
      99                 :          0 :   g_main_loop_quit (loop);
     100                 :          0 :   return G_SOURCE_REMOVE;
     101                 :            : }
     102                 :            : 
     103                 :            : static void
     104                 :          0 : test_overflow (void)
     105                 :            : {
     106                 :            :   gint sv[2];
     107                 :            :   gint n;
     108                 :            :   GSocket *socket;
     109                 :            :   GSocketConnection *socket_connection;
     110                 :            :   GDBusConnection *producer, *consumer;
     111                 :            :   GError *error;
     112                 :            :   GTimer *timer;
     113                 :            :   gint n_messages_received;  /* (atomic) */
     114                 :            :   gint n_messages_sent;  /* (atomic) */
     115                 :            : 
     116                 :          0 :   g_assert_cmpint (socketpair (AF_UNIX, SOCK_STREAM, 0, sv), ==, 0);
     117                 :            : 
     118                 :          0 :   error = NULL;
     119                 :          0 :   socket = g_socket_new_from_fd (sv[0], &error);
     120                 :          0 :   g_assert_no_error (error);
     121                 :          0 :   socket_connection = g_socket_connection_factory_create_connection (socket);
     122                 :          0 :   g_assert (socket_connection != NULL);
     123                 :          0 :   g_object_unref (socket);
     124                 :          0 :   producer = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
     125                 :            :                                          NULL, /* guid */
     126                 :            :                                          G_DBUS_CONNECTION_FLAGS_NONE,
     127                 :            :                                          NULL, /* GDBusAuthObserver */
     128                 :            :                                          NULL, /* GCancellable */
     129                 :            : 
     130                 :            :                                          &error);
     131                 :          0 :   g_dbus_connection_set_exit_on_close (producer, TRUE);
     132                 :          0 :   g_assert_no_error (error);
     133                 :          0 :   g_object_unref (socket_connection);
     134                 :          0 :   g_atomic_int_set (&n_messages_sent, 0);
     135                 :          0 :   g_dbus_connection_add_filter (producer, overflow_filter_func, (gpointer) &n_messages_sent, NULL);
     136                 :            : 
     137                 :            :   /* send enough data that we get an EAGAIN */
     138         [ #  # ]:          0 :   for (n = 0; n < OVERFLOW_NUM_SIGNALS; n++)
     139                 :            :     {
     140                 :          0 :       error = NULL;
     141                 :          0 :       g_dbus_connection_emit_signal (producer,
     142                 :            :                                      NULL, /* destination */
     143                 :            :                                      "/org/foo/Object",
     144                 :            :                                      "org.foo.Interface",
     145                 :            :                                      "Member",
     146                 :            :                                      g_variant_new ("(s)", "a string"),
     147                 :            :                                      &error);
     148                 :          0 :       g_assert_no_error (error);
     149                 :            :     }
     150                 :            : 
     151                 :            :   /* sleep for 0.5 sec (to allow the GDBus IO thread to fill up the
     152                 :            :    * kernel buffers) and verify that n_messages_sent <
     153                 :            :    * OVERFLOW_NUM_SIGNALS
     154                 :            :    *
     155                 :            :    * This is to verify that not all the submitted messages have been
     156                 :            :    * sent to the underlying transport.
     157                 :            :    */
     158                 :          0 :   g_timeout_add (500, overflow_on_500ms_later_func, NULL);
     159                 :          0 :   g_main_loop_run (loop);
     160                 :          0 :   g_assert_cmpint (g_atomic_int_get (&n_messages_sent), <, OVERFLOW_NUM_SIGNALS);
     161                 :            : 
     162                 :            :   /* now suck it all out as a client, and add it up */
     163                 :          0 :   socket = g_socket_new_from_fd (sv[1], &error);
     164                 :          0 :   g_assert_no_error (error);
     165                 :          0 :   socket_connection = g_socket_connection_factory_create_connection (socket);
     166                 :          0 :   g_assert (socket_connection != NULL);
     167                 :          0 :   g_object_unref (socket);
     168                 :          0 :   consumer = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
     169                 :            :                                          NULL, /* guid */
     170                 :            :                                          G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING,
     171                 :            :                                          NULL, /* GDBusAuthObserver */
     172                 :            :                                          NULL, /* GCancellable */
     173                 :            :                                          &error);
     174                 :          0 :   g_assert_no_error (error);
     175                 :          0 :   g_object_unref (socket_connection);
     176                 :          0 :   g_atomic_int_set (&n_messages_received, 0);
     177                 :          0 :   g_dbus_connection_add_filter (consumer, overflow_filter_func, (gpointer) &n_messages_received, NULL);
     178                 :          0 :   g_dbus_connection_start_message_processing (consumer);
     179                 :            : 
     180                 :          0 :   timer = g_timer_new ();
     181                 :          0 :   g_timer_start (timer);
     182                 :            : 
     183   [ #  #  #  # ]:          0 :   while (g_atomic_int_get (&n_messages_received) < OVERFLOW_NUM_SIGNALS && g_timer_elapsed (timer, NULL) < OVERFLOW_TIMEOUT_SEC)
     184                 :          0 :       g_main_context_iteration (NULL, FALSE);
     185                 :            : 
     186                 :          0 :   g_assert_cmpint (g_atomic_int_get (&n_messages_sent), ==, OVERFLOW_NUM_SIGNALS);
     187                 :          0 :   g_assert_cmpint (g_atomic_int_get (&n_messages_received), ==, OVERFLOW_NUM_SIGNALS);
     188                 :            : 
     189                 :          0 :   g_timer_destroy (timer);
     190                 :          0 :   g_object_unref (consumer);
     191                 :          0 :   g_object_unref (producer);
     192                 :          0 : }
     193                 :            : #else
     194                 :            : static void
     195                 :            : test_overflow (void)
     196                 :            : {
     197                 :            :   /* TODO: test this with e.g. GWin32InputStream/GWin32OutputStream */
     198                 :            : }
     199                 :            : #endif
     200                 :            : 
     201                 :            : /* ---------------------------------------------------------------------------------------------------- */
     202                 :            : 
     203                 :            : 
     204                 :            : int
     205                 :          0 : main (int   argc,
     206                 :            :       char *argv[])
     207                 :            : {
     208                 :            :   gint ret;
     209                 :          0 :   GDBusNodeInfo *introspection_data = NULL;
     210                 :          0 :   gchar *tmpdir = NULL;
     211                 :            : 
     212                 :          0 :   g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
     213                 :            : 
     214                 :          0 :   introspection_data = g_dbus_node_info_new_for_xml (test_interface_introspection_xml, NULL);
     215                 :          0 :   g_assert (introspection_data != NULL);
     216                 :          0 :   test_interface_introspection_data = introspection_data->interfaces[0];
     217                 :            : 
     218                 :          0 :   test_guid = g_dbus_generate_guid ();
     219                 :            : 
     220         [ #  # ]:          0 :   if (is_unix)
     221                 :            :     {
     222                 :          0 :       tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
     223                 :          0 :       tmp_address = g_strdup_printf ("unix:tmpdir=%s", tmpdir);
     224                 :            :     }
     225                 :            :   else
     226                 :          0 :     tmp_address = g_strdup ("nonce-tcp:");
     227                 :            : 
     228                 :            :   /* all the tests rely on a shared main loop */
     229                 :          0 :   loop = g_main_loop_new (NULL, FALSE);
     230                 :            : 
     231                 :          0 :   g_test_add_func ("/gdbus/overflow", test_overflow);
     232                 :            : 
     233                 :          0 :   ret = g_test_run();
     234                 :            : 
     235                 :          0 :   g_main_loop_unref (loop);
     236                 :          0 :   g_free (test_guid);
     237                 :          0 :   g_dbus_node_info_unref (introspection_data);
     238         [ #  # ]:          0 :   if (is_unix)
     239                 :          0 :     g_free (tmp_address);
     240         [ #  # ]:          0 :   if (tmpdir)
     241                 :            :     {
     242                 :          0 :       g_rmdir (tmpdir);
     243                 :          0 :       g_free (tmpdir);
     244                 :            :     }
     245                 :            : 
     246                 :          0 :   return ret;
     247                 :            : }

Generated by: LCOV version 1.14