Home | History | Annotate | Download | only in gobject
      1 /* GObject - GLib Type, Object, Parameter and Signal Library
      2  * override.c: Closure override test program
      3  * Copyright (C) 2001, James Henstridge
      4  * Copyright (C) 2003, Red Hat, Inc.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Lesser General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library 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.  See the GNU
     14  * Lesser General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Lesser General
     17  * Public License along with this library; if not, write to the
     18  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
     19  * Boston, MA 02111-1307, USA.
     20  */
     21 
     22 #undef	G_LOG_DOMAIN
     23 #define	G_LOG_DOMAIN "TestOverride"
     24 
     25 #undef G_DISABLE_ASSERT
     26 #undef G_DISABLE_CHECKS
     27 #undef G_DISABLE_CAST_CHECKS
     28 
     29 #undef VERBOSE
     30 
     31 #include <string.h>
     32 
     33 #include <glib.h>
     34 #include <glib-object.h>
     35 
     36 #include "testcommon.h"
     37 
     38 static guint foo_signal_id = 0;
     39 static guint bar_signal_id = 0;
     40 static guint baz_signal_id = 0;
     41 
     42 static GType test_i_get_type (void);
     43 static GType test_a_get_type (void);
     44 static GType test_b_get_type (void);
     45 static GType test_c_get_type (void);
     46 
     47 static void  record (const gchar *str);
     48 
     49 #define TEST_TYPE_I (test_i_get_type ())
     50 
     51 typedef struct _TestI TestI;
     52 typedef struct _TestIClass TestIClass;
     53 
     54 struct _TestIClass
     55 {
     56   GTypeInterface base_iface;
     57 };
     58 
     59 static void
     60 test_i_foo (TestI *self)
     61 {
     62   record ("TestI::foo");
     63 }
     64 
     65 static void
     66 test_i_default_init (gpointer g_class)
     67 {
     68   foo_signal_id = g_signal_newv ("foo",
     69 				 TEST_TYPE_I,
     70 				 G_SIGNAL_RUN_LAST,
     71 				 g_cclosure_new(G_CALLBACK(test_i_foo),
     72 						NULL, NULL),
     73 				 NULL, NULL,
     74 				 g_cclosure_marshal_VOID__VOID,
     75 				 G_TYPE_NONE, 0, NULL);
     76 }
     77 
     78 static DEFINE_IFACE (TestI, test_i, NULL, test_i_default_init)
     79 
     80 #define TEST_TYPE_A (test_a_get_type())
     81 
     82      typedef struct _TestA TestA;
     83      typedef struct _TestAClass TestAClass;
     84 
     85 struct _TestA {
     86   GObject parent;
     87 };
     88 struct _TestAClass {
     89   GObjectClass parent_class;
     90 
     91   void (* bar) (TestA *self);
     92 };
     93 
     94 static void
     95 test_a_foo (TestI *self)
     96 {
     97   GValue args[1] = { { 0, } };
     98 
     99   record ("TestA::foo");
    100 
    101   g_value_init (&args[0], TEST_TYPE_A);
    102   g_value_set_object (&args[0], self);
    103 
    104   g_assert (g_signal_get_invocation_hint (self)->signal_id == foo_signal_id);
    105   g_signal_chain_from_overridden (args, NULL);
    106 
    107   g_value_unset (&args[0]);
    108 }
    109 
    110 static void
    111 test_a_bar (TestA *self)
    112 {
    113   record ("TestA::bar");
    114 }
    115 
    116 static gchar *
    117 test_a_baz (TestA    *self,
    118             GObject  *object,
    119             gpointer  pointer)
    120 {
    121   record ("TestA::baz");
    122 
    123   g_assert (object == G_OBJECT (self));
    124   g_assert (GPOINTER_TO_INT (pointer) == 23);
    125 
    126   return g_strdup ("TestA::baz");
    127 }
    128 
    129 static void
    130 test_a_class_init (TestAClass *class)
    131 {
    132   class->bar = test_a_bar;
    133 
    134   bar_signal_id = g_signal_new ("bar",
    135 				TEST_TYPE_A,
    136 				G_SIGNAL_RUN_LAST,
    137 				G_STRUCT_OFFSET (TestAClass, bar),
    138 				NULL, NULL,
    139 				g_cclosure_marshal_VOID__VOID,
    140 				G_TYPE_NONE, 0, NULL);
    141 
    142   baz_signal_id = g_signal_new_class_handler ("baz",
    143                                               TEST_TYPE_A,
    144                                               G_SIGNAL_RUN_LAST,
    145                                               G_CALLBACK (test_a_baz),
    146                                               NULL, NULL,
    147                                               g_cclosure_marshal_STRING__OBJECT_POINTER,
    148                                               G_TYPE_STRING, 2,
    149                                               G_TYPE_OBJECT,
    150                                               G_TYPE_POINTER);
    151 }
    152 
    153 static void
    154 test_a_interface_init (TestIClass *iface)
    155 {
    156   g_signal_override_class_closure (foo_signal_id,
    157 				   TEST_TYPE_A,
    158 				   g_cclosure_new (G_CALLBACK (test_a_foo),
    159 						   NULL, NULL));
    160 }
    161 
    162 static DEFINE_TYPE_FULL (TestA, test_a,
    163 			 test_a_class_init, NULL, NULL,
    164 			 G_TYPE_OBJECT,
    165 			 INTERFACE (test_a_interface_init, TEST_TYPE_I))
    166 
    167 #define TEST_TYPE_B (test_b_get_type())
    168 
    169 typedef struct _TestB TestB;
    170 typedef struct _TestBClass TestBClass;
    171 
    172 struct _TestB {
    173   TestA parent;
    174 };
    175 struct _TestBClass {
    176   TestAClass parent_class;
    177 };
    178 
    179 static void
    180 test_b_foo (TestI *self)
    181 {
    182   GValue args[1] = { { 0, } };
    183 
    184   record ("TestB::foo");
    185 
    186   g_value_init (&args[0], TEST_TYPE_A);
    187   g_value_set_object (&args[0], self);
    188 
    189   g_assert (g_signal_get_invocation_hint (self)->signal_id == foo_signal_id);
    190   g_signal_chain_from_overridden (args, NULL);
    191 
    192   g_value_unset (&args[0]);
    193 }
    194 
    195 static void
    196 test_b_bar (TestA *self)
    197 {
    198   GValue args[1] = { { 0, } };
    199 
    200   record ("TestB::bar");
    201 
    202   g_value_init (&args[0], TEST_TYPE_A);
    203   g_value_set_object (&args[0], self);
    204 
    205   g_assert (g_signal_get_invocation_hint (self)->signal_id == bar_signal_id);
    206   g_signal_chain_from_overridden (args, NULL);
    207 
    208   g_value_unset (&args[0]);
    209 }
    210 
    211 static gchar *
    212 test_b_baz (TestA    *self,
    213             GObject  *object,
    214             gpointer  pointer)
    215 {
    216   gchar *retval = NULL;
    217 
    218   record ("TestB::baz");
    219 
    220   g_assert (object == G_OBJECT (self));
    221   g_assert (GPOINTER_TO_INT (pointer) == 23);
    222 
    223   g_signal_chain_from_overridden_handler (self, object, pointer, &retval);
    224 
    225   if (retval)
    226     {
    227       gchar *tmp = g_strconcat (retval , ",TestB::baz", NULL);
    228       g_free (retval);
    229       retval = tmp;
    230     }
    231 
    232   return retval;
    233 }
    234 
    235 static void
    236 test_b_class_init (TestBClass *class)
    237 {
    238   g_signal_override_class_closure (foo_signal_id,
    239 				   TEST_TYPE_B,
    240 				   g_cclosure_new (G_CALLBACK (test_b_foo),
    241 						   NULL, NULL));
    242   g_signal_override_class_closure (bar_signal_id,
    243 				   TEST_TYPE_B,
    244 				   g_cclosure_new (G_CALLBACK (test_b_bar),
    245 						   NULL, NULL));
    246   g_signal_override_class_handler ("baz",
    247 				   TEST_TYPE_B,
    248 				   G_CALLBACK (test_b_baz));
    249 }
    250 
    251 static DEFINE_TYPE (TestB, test_b,
    252 		    test_b_class_init, NULL, NULL,
    253 		    TEST_TYPE_A)
    254 
    255 #define TEST_TYPE_C (test_c_get_type())
    256 
    257 typedef struct _TestC TestC;
    258 typedef struct _TestCClass TestCClass;
    259 
    260 struct _TestC {
    261   TestB parent;
    262 };
    263 struct _TestCClass {
    264   TestBClass parent_class;
    265 };
    266 
    267 static void
    268 test_c_foo (TestI *self)
    269 {
    270   GValue args[1] = { { 0, } };
    271 
    272   record ("TestC::foo");
    273 
    274   g_value_init (&args[0], TEST_TYPE_A);
    275   g_value_set_object (&args[0], self);
    276 
    277   g_assert (g_signal_get_invocation_hint (self)->signal_id == foo_signal_id);
    278   g_signal_chain_from_overridden (args, NULL);
    279 
    280   g_value_unset (&args[0]);
    281 }
    282 
    283 static void
    284 test_c_bar (TestA *self)
    285 {
    286   GValue args[1] = { { 0, } };
    287 
    288   record ("TestC::bar");
    289 
    290   g_value_init (&args[0], TEST_TYPE_A);
    291   g_value_set_object (&args[0], self);
    292 
    293   g_assert (g_signal_get_invocation_hint (self)->signal_id == bar_signal_id);
    294   g_signal_chain_from_overridden (args, NULL);
    295 
    296   g_value_unset (&args[0]);
    297 }
    298 
    299 static gchar *
    300 test_c_baz (TestA    *self,
    301             GObject  *object,
    302             gpointer  pointer)
    303 {
    304   gchar *retval = NULL;
    305 
    306   record ("TestC::baz");
    307 
    308   g_assert (object == G_OBJECT (self));
    309   g_assert (GPOINTER_TO_INT (pointer) == 23);
    310 
    311   g_signal_chain_from_overridden_handler (self, object, pointer, &retval);
    312 
    313   if (retval)
    314     {
    315       gchar *tmp = g_strconcat (retval , ",TestC::baz", NULL);
    316       g_free (retval);
    317       retval = tmp;
    318     }
    319 
    320   return retval;
    321 }
    322 
    323 static void
    324 test_c_class_init (TestBClass *class)
    325 {
    326   g_signal_override_class_closure (foo_signal_id,
    327 				   TEST_TYPE_C,
    328 				   g_cclosure_new (G_CALLBACK (test_c_foo),
    329 						   NULL, NULL));
    330   g_signal_override_class_closure (bar_signal_id,
    331 				   TEST_TYPE_C,
    332 				   g_cclosure_new (G_CALLBACK (test_c_bar),
    333 						   NULL, NULL));
    334   g_signal_override_class_handler ("baz",
    335 				   TEST_TYPE_C,
    336 				   G_CALLBACK (test_c_baz));
    337 }
    338 
    339 
    340 static DEFINE_TYPE (TestC, test_c,
    341 		    test_c_class_init, NULL, NULL,
    342 		    TEST_TYPE_B)
    343 
    344 static GString *test_string = NULL;
    345 gboolean failed = FALSE;
    346 
    347 static void
    348 record (const gchar *str)
    349 {
    350   if (test_string->len)
    351     g_string_append_c (test_string, ',');
    352   g_string_append (test_string, str);
    353 }
    354 
    355 static void
    356 test (GType        type,
    357       const gchar *signal,
    358       const gchar *expected,
    359       const gchar *expected_retval)
    360 {
    361   GObject *self = g_object_new (type, NULL);
    362 
    363   test_string = g_string_new (NULL);
    364 
    365   if (strcmp (signal, "baz"))
    366     {
    367       g_signal_emit_by_name (self, signal);
    368     }
    369   else
    370     {
    371       gchar *ret;
    372 
    373       g_signal_emit_by_name (self, signal, self, GINT_TO_POINTER (23), &ret);
    374 
    375       if (strcmp (ret, expected_retval) != 0)
    376         failed = TRUE;
    377     }
    378 
    379 #ifndef VERBOSE
    380   if (strcmp (test_string->str, expected) != 0)
    381 #endif
    382     {
    383       g_printerr ("*** emitting %s on a %s instance\n"
    384 		  "    Expecting: %s\n"
    385 		  "    Got: %s\n",
    386 		  signal, g_type_name (type),
    387 		  expected,
    388 		  test_string->str);
    389 
    390       if (strcmp (test_string->str, expected) != 0)
    391 	failed = TRUE;
    392     }
    393 
    394   g_string_free (test_string, TRUE);
    395 }
    396 
    397 int
    398 main (int argc, char **argv)
    399 {
    400   g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
    401 			  G_LOG_LEVEL_WARNING |
    402 			  G_LOG_LEVEL_CRITICAL);
    403   g_type_init();
    404 
    405   test (TEST_TYPE_A, "foo", "TestA::foo,TestI::foo", NULL);
    406   test (TEST_TYPE_A, "bar", "TestA::bar", NULL);
    407   test (TEST_TYPE_A, "baz", "TestA::baz", "TestA::baz");
    408 
    409   test (TEST_TYPE_B, "foo", "TestB::foo,TestA::foo,TestI::foo", NULL);
    410   test (TEST_TYPE_B, "bar", "TestB::bar,TestA::bar", NULL);
    411   test (TEST_TYPE_B, "baz", "TestB::baz,TestA::baz", "TestA::baz,TestB::baz");
    412 
    413   test (TEST_TYPE_C, "foo", "TestC::foo,TestB::foo,TestA::foo,TestI::foo", NULL);
    414   test (TEST_TYPE_C, "bar", "TestC::bar,TestB::bar,TestA::bar", NULL);
    415   test (TEST_TYPE_C, "baz", "TestC::baz,TestB::baz,TestA::baz", "TestA::baz,TestB::baz,TestC::baz");
    416 
    417   return failed ? 1 : 0;
    418 }
    419