LCOV - code coverage report
Current view: top level - glib/gobject/tests - dynamictests.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 100 119 84.0 %
Date: 2024-04-30 05:17:35 Functions: 25 28 89.3 %
Branches: 21 32 65.6 %

           Branch data     Line data    Source code
       1                 :            : /* GLib testing framework examples and tests
       2                 :            :  * Copyright (C) 2008 Imendio AB
       3                 :            :  * Authors: Tim Janik
       4                 :            :  *
       5                 :            :  * SPDX-License-Identifier: LicenseRef-old-glib-tests
       6                 :            :  *
       7                 :            :  * This work is provided "as is"; redistribution and modification
       8                 :            :  * in whole or in part, in any medium, physical or electronic is
       9                 :            :  * permitted without restriction.
      10                 :            :  *
      11                 :            :  * This work is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      14                 :            :  *
      15                 :            :  * In no event shall the authors or contributors be liable for any
      16                 :            :  * direct, indirect, incidental, special, exemplary, or consequential
      17                 :            :  * damages (including, but not limited to, procurement of substitute
      18                 :            :  * goods or services; loss of use, data, or profits; or business
      19                 :            :  * interruption) however caused and on any theory of liability, whether
      20                 :            :  * in contract, strict liability, or tort (including negligence or
      21                 :            :  * otherwise) arising in any way out of the use of this software, even
      22                 :            :  * if advised of the possibility of such damage.
      23                 :            :  */
      24                 :            : #include <glib.h>
      25                 :            : #include <glib-object.h>
      26                 :            : 
      27                 :            : /* This test tests the macros for defining dynamic types.
      28                 :            :  */
      29                 :            : 
      30                 :            : static GMutex sync_mutex;
      31                 :            : static gboolean loaded = FALSE;
      32                 :            : 
      33                 :            : /* MODULE */
      34                 :            : typedef struct _TestModule      TestModule;
      35                 :            : typedef struct _TestModuleClass TestModuleClass;
      36                 :            : 
      37                 :            : #define TEST_TYPE_MODULE              (test_module_get_type ())
      38                 :            : #define TEST_MODULE(module)           (G_TYPE_CHECK_INSTANCE_CAST ((module), TEST_TYPE_MODULE, TestModule))
      39                 :            : #define TEST_MODULE_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), TEST_TYPE_MODULE, TestModuleClass))
      40                 :            : #define TEST_IS_MODULE(module)        (G_TYPE_CHECK_INSTANCE_TYPE ((module), TEST_TYPE_MODULE))
      41                 :            : #define TEST_IS_MODULE_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), TEST_TYPE_MODULE))
      42                 :            : #define TEST_MODULE_GET_CLASS(module) (G_TYPE_INSTANCE_GET_CLASS ((module), TEST_TYPE_MODULE, TestModuleClass))
      43                 :            : typedef void (*TestModuleRegisterFunc) (GTypeModule *module);
      44                 :            : 
      45                 :            : struct _TestModule
      46                 :            : {
      47                 :            :   GTypeModule parent_instance;
      48                 :            : 
      49                 :            :   TestModuleRegisterFunc register_func;
      50                 :            : };
      51                 :            : 
      52                 :            : struct _TestModuleClass
      53                 :            : {
      54                 :            :   GTypeModuleClass parent_class;
      55                 :            : };
      56                 :            : 
      57                 :            : static GType test_module_get_type (void);
      58                 :            : 
      59                 :            : static gboolean
      60                 :          4 : test_module_load (GTypeModule *module)
      61                 :            : {
      62                 :          4 :   TestModule *test_module = TEST_MODULE (module);
      63                 :            : 
      64                 :          4 :   test_module->register_func (module);
      65                 :            : 
      66                 :          4 :   return TRUE;
      67                 :            : }
      68                 :            : 
      69                 :            : static void
      70                 :          2 : test_module_unload (GTypeModule *module)
      71                 :            : {
      72                 :          2 : }
      73                 :            : 
      74                 :            : static void
      75                 :          1 : test_module_class_init (TestModuleClass *class)
      76                 :            : {
      77                 :          1 :   GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
      78                 :            : 
      79                 :          1 :   module_class->load = test_module_load;
      80                 :          1 :   module_class->unload = test_module_unload;
      81                 :          1 : }
      82                 :            : 
      83                 :          6 : static GType test_module_get_type (void)
      84                 :            : {
      85                 :            :   static GType object_type = 0;
      86                 :            : 
      87         [ +  + ]:          6 :   if (!object_type) {
      88                 :            :     static const GTypeInfo object_info =
      89                 :            :       {
      90                 :            :         sizeof (TestModuleClass),
      91                 :            :         (GBaseInitFunc) NULL,
      92                 :            :         (GBaseFinalizeFunc) NULL,
      93                 :            :         (GClassInitFunc) test_module_class_init,
      94                 :            :         (GClassFinalizeFunc) NULL,
      95                 :            :         NULL,
      96                 :            :         sizeof (TestModule),
      97                 :            :         0,
      98                 :            :         (GInstanceInitFunc)NULL,
      99                 :            :         NULL,
     100                 :            :       };
     101                 :          1 :     object_type = g_type_register_static (G_TYPE_TYPE_MODULE, "TestModule", &object_info, 0);
     102                 :            :   }
     103                 :          6 :   return object_type;
     104                 :            : }
     105                 :            : 
     106                 :            : 
     107                 :            : static GTypeModule *
     108                 :          2 : test_module_new (TestModuleRegisterFunc register_func)
     109                 :            : {
     110                 :          2 :   TestModule *test_module = g_object_new (TEST_TYPE_MODULE, NULL);
     111                 :          2 :   GTypeModule *module = G_TYPE_MODULE (test_module);
     112                 :            : 
     113                 :          2 :   test_module->register_func = register_func;
     114                 :            : 
     115                 :            :   /* Register the types initially */
     116                 :          2 :   g_type_module_use (module);
     117                 :          2 :   g_type_module_unuse (module);
     118                 :            : 
     119                 :          2 :   return G_TYPE_MODULE (module);
     120                 :            : }
     121                 :            : 
     122                 :            : 
     123                 :            : 
     124                 :            : #define DYNAMIC_OBJECT_TYPE (dynamic_object_get_type ())
     125                 :            : 
     126                 :            : typedef GObject DynamicObject;
     127                 :            : typedef struct _DynamicObjectClass DynamicObjectClass;
     128                 :            : 
     129                 :            : struct _DynamicObjectClass
     130                 :            : {
     131                 :            :   GObjectClass parent_class;
     132                 :            :   guint val;
     133                 :            : };
     134                 :            : 
     135                 :            : static GType dynamic_object_get_type (void);
     136         [ -  + ]:        104 : G_DEFINE_DYNAMIC_TYPE(DynamicObject, dynamic_object, G_TYPE_OBJECT)
     137                 :            : 
     138                 :            : static void
     139                 :          1 : dynamic_object_class_init (DynamicObjectClass *class)
     140                 :            : {
     141                 :          1 :   class->val = 42;
     142                 :          1 :   g_assert (loaded == FALSE);
     143                 :          1 :   loaded = TRUE;
     144                 :          1 : }
     145                 :            : 
     146                 :            : static void
     147                 :          0 : dynamic_object_class_finalize (DynamicObjectClass *class)
     148                 :            : {
     149                 :          0 :   g_assert (loaded == TRUE);
     150                 :          0 :   loaded = FALSE;
     151                 :          0 : }
     152                 :            : 
     153                 :            : static void
     154                 :          0 : dynamic_object_init (DynamicObject *dynamic_object)
     155                 :            : {
     156                 :          0 : }
     157                 :            : 
     158                 :            : 
     159                 :            : static void
     160                 :          2 : module_register (GTypeModule *module)
     161                 :            : {
     162                 :          2 :   dynamic_object_register_type (module);
     163                 :          2 : }
     164                 :            : 
     165                 :            : #define N_THREADS 100
     166                 :            : #define N_REFS 10000
     167                 :            : 
     168                 :            : static gpointer
     169                 :        100 : ref_unref_thread (gpointer data)
     170                 :            : {
     171                 :            :   gint i;
     172                 :            :   /* first, synchronize with other threads,
     173                 :            :    */
     174         [ -  + ]:        100 :   if (g_test_verbose())
     175                 :          0 :     g_printerr ("WAITING!\n");
     176                 :        100 :   g_mutex_lock (&sync_mutex);
     177                 :        100 :   g_mutex_unlock (&sync_mutex);
     178         [ -  + ]:        100 :   if (g_test_verbose ())
     179                 :          0 :     g_printerr ("STARTING\n");
     180                 :            : 
     181                 :            :   /* ref/unref the klass 10000000 times */
     182         [ +  + ]:    1000100 :   for (i = N_REFS; i; i--) {
     183         [ -  + ]:    1000000 :     if (g_test_verbose ())
     184         [ #  # ]:          0 :       if (i % 10)
     185                 :          0 :         g_printerr ("%d\n", i);
     186                 :    1000000 :     g_type_class_unref (g_type_class_ref ((GType) data));
     187                 :            :   }
     188                 :            : 
     189         [ -  + ]:        100 :   if (g_test_verbose())
     190                 :          0 :     g_printerr ("DONE !\n");
     191                 :            : 
     192                 :        100 :   return NULL;
     193                 :            : }
     194                 :            : 
     195                 :            : static void
     196                 :          1 : test_multithreaded_dynamic_type_init (void)
     197                 :            : {
     198                 :            :   GTypeModule *module;
     199                 :            :   DynamicObjectClass *class;
     200                 :            :   /* Create N_THREADS threads that are going to just ref/unref a class */
     201                 :            :   GThread *threads[N_THREADS];
     202                 :            :   guint i;
     203                 :            : 
     204                 :          1 :   module = test_module_new (module_register);
     205                 :          1 :   g_assert (module != NULL);
     206                 :            : 
     207                 :            :   /* Not loaded until we call ref for the first time */
     208                 :          1 :   class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
     209                 :          1 :   g_assert (class == NULL);
     210                 :          1 :   g_assert (!loaded);
     211                 :            : 
     212                 :            :   /* pause newly created threads */
     213                 :          1 :   g_mutex_lock (&sync_mutex);
     214                 :            : 
     215                 :            :   /* create threads */
     216         [ +  + ]:        101 :   for (i = 0; i < N_THREADS; i++) {
     217                 :        100 :     threads[i] = g_thread_new ("test", ref_unref_thread, (gpointer) DYNAMIC_OBJECT_TYPE);
     218                 :            :   }
     219                 :            : 
     220                 :            :   /* execute threads */
     221                 :          1 :   g_mutex_unlock (&sync_mutex);
     222                 :            : 
     223         [ +  + ]:        101 :   for (i = 0; i < N_THREADS; i++) {
     224                 :        100 :     g_thread_join (threads[i]);
     225                 :            :   }
     226                 :          1 : }
     227                 :            : 
     228                 :            : enum
     229                 :            : {
     230                 :            :   PROP_0,
     231                 :            :   PROP_FOO
     232                 :            : };
     233                 :            : 
     234                 :            : typedef struct _DynObj DynObj;
     235                 :            : typedef struct _DynObjClass DynObjClass;
     236                 :            : typedef struct _DynIfaceInterface DynIfaceInterface;
     237                 :            : 
     238                 :            : struct _DynObj
     239                 :            : {
     240                 :            :   GObject obj;
     241                 :            : 
     242                 :            :   gint foo;
     243                 :            : };
     244                 :            : 
     245                 :            : struct _DynObjClass
     246                 :            : {
     247                 :            :   GObjectClass class;
     248                 :            : };
     249                 :            : 
     250                 :            : struct _DynIfaceInterface
     251                 :            : {
     252                 :            :   GTypeInterface iface;
     253                 :            : };
     254                 :            : 
     255                 :            : static void dyn_obj_iface_init (DynIfaceInterface *iface);
     256                 :            : 
     257                 :            : static GType dyn_iface_get_type (void);
     258   [ +  +  +  -  :          2 : G_DEFINE_INTERFACE (DynIface, dyn_iface, G_TYPE_OBJECT)
                   +  + ]
     259                 :            : 
     260                 :            : static GType dyn_obj_get_type (void);
     261         [ -  + ]:          4 : G_DEFINE_DYNAMIC_TYPE_EXTENDED(DynObj, dyn_obj, G_TYPE_OBJECT, 0,
     262                 :            :                       G_IMPLEMENT_INTERFACE_DYNAMIC(dyn_iface_get_type (), dyn_obj_iface_init))
     263                 :            : 
     264                 :            : 
     265                 :            : static void
     266                 :          1 : dyn_iface_default_init (DynIfaceInterface *iface)
     267                 :            : {
     268                 :          1 :   g_object_interface_install_property (iface,
     269                 :            :     g_param_spec_int ("foo", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE));
     270                 :          1 : }
     271                 :            : 
     272                 :            : static void
     273                 :          1 : dyn_obj_iface_init (DynIfaceInterface *iface)
     274                 :            : {
     275                 :          1 : }
     276                 :            : 
     277                 :            : static void
     278                 :          1 : dyn_obj_init (DynObj *obj)
     279                 :            : {
     280                 :          1 :   obj->foo = 0;
     281                 :          1 : }
     282                 :            : 
     283                 :            : static void
     284                 :          1 : set_prop (GObject      *object,
     285                 :            :           guint         prop_id,
     286                 :            :           const GValue *value,
     287                 :            :           GParamSpec   *pspec)
     288                 :            : {
     289                 :          1 :   DynObj *obj = (DynObj *)object;
     290                 :            : 
     291         [ +  - ]:          1 :   switch (prop_id)
     292                 :            :     {
     293                 :          1 :     case PROP_FOO:
     294                 :          1 :       obj->foo = g_value_get_int (value);
     295                 :          1 :       break;
     296                 :          0 :     default:
     297                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     298                 :          0 :       break;
     299                 :            :     }
     300                 :          1 : }
     301                 :            : 
     302                 :            : static void
     303                 :          1 : get_prop (GObject    *object,
     304                 :            :           guint       prop_id,
     305                 :            :           GValue     *value,
     306                 :            :           GParamSpec *pspec)
     307                 :            : {
     308                 :          1 :   DynObj *obj = (DynObj *)object;
     309                 :            : 
     310         [ +  - ]:          1 :   switch (prop_id)
     311                 :            :     {
     312                 :          1 :     case PROP_FOO:
     313                 :          1 :       g_value_set_int (value, obj->foo);
     314                 :          1 :       break;
     315                 :          0 :     default:
     316                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     317                 :          0 :       break;
     318                 :            :     }
     319                 :          1 : }
     320                 :            : 
     321                 :            : static void
     322                 :          1 : dyn_obj_class_init (DynObjClass *class)
     323                 :            : {
     324                 :          1 :   GObjectClass *object_class = G_OBJECT_CLASS (class);
     325                 :            : 
     326                 :          1 :   object_class->set_property = set_prop;
     327                 :          1 :   object_class->get_property = get_prop;
     328                 :            : 
     329                 :          1 :   g_object_class_override_property (object_class, PROP_FOO, "foo");
     330                 :          1 : }
     331                 :            : 
     332                 :            : static void
     333                 :          0 : dyn_obj_class_finalize (DynObjClass *class)
     334                 :            : {
     335                 :          0 : }
     336                 :            : 
     337                 :            : static void
     338                 :          2 : mod_register (GTypeModule *module)
     339                 :            : {
     340                 :          2 :   dyn_obj_register_type (module);
     341                 :          2 : }
     342                 :            : 
     343                 :            : static void
     344                 :          1 : test_dynamic_interface_properties (void)
     345                 :            : {
     346                 :            :   GTypeModule *module;
     347                 :            :   DynObj *obj;
     348                 :            :   gint val;
     349                 :            : 
     350                 :          1 :   module = test_module_new (mod_register);
     351                 :          1 :   g_assert (module != NULL);
     352                 :            : 
     353                 :          1 :   obj = g_object_new (dyn_obj_get_type (), "foo", 1, NULL);
     354                 :          1 :   g_object_get (obj, "foo", &val, NULL);
     355                 :          1 :   g_assert_cmpint (val, ==, 1);
     356                 :            : 
     357                 :          1 :   g_object_unref (obj);
     358                 :          1 : }
     359                 :            : 
     360                 :            : int
     361                 :          1 : main (int   argc,
     362                 :            :       char *argv[])
     363                 :            : {
     364                 :          1 :   g_test_init (&argc, &argv, NULL);
     365                 :            : 
     366                 :          1 :   g_test_add_func ("/GObject/threaded-dynamic-ref-unref-init", test_multithreaded_dynamic_type_init);
     367                 :          1 :   g_test_add_func ("/GObject/dynamic-interface-properties", test_dynamic_interface_properties);
     368                 :            : 
     369                 :          1 :   return g_test_run();
     370                 :            : }

Generated by: LCOV version 1.14