Home | History | Annotate | Download | only in gobject
      1 /* GObject - GLib Type, Object, Parameter and Signal Library
      2  * Copyright (C) 2001, 2003 Red Hat, Inc.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Lesser General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General
     15  * Public License along with this library; if not, write to the
     16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
     17  * Boston, MA 02111-1307, USA.
     18  */
     19 
     20 #undef	G_LOG_DOMAIN
     21 #define	G_LOG_DOMAIN "TestIfaceInherit"
     22 
     23 #undef G_DISABLE_ASSERT
     24 #undef G_DISABLE_CHECKS
     25 #undef G_DISABLE_CAST_CHECKS
     26 
     27 #include <glib-object.h>
     28 
     29 #include "testcommon.h"
     30 #include "testmodule.h"
     31 
     32 /* This test tests inheritance of interface. We two object
     33  * class BaseObject and DerivedObject we add an interface
     34  * to BaseObject:
     35  *
     36  * I1) Before DerivedObject is registered
     37  * I2) After DerivedObject is registered, but before
     38  *     DerivedObject is class initialized
     39  * I3) During DerivedObject's class_init
     40  * I4) After DerivedObject's class init
     41  *
     42  * We also do some tests of overriding.
     43  *
     44  * I5) We add an interface to BaseObject, then add the same
     45  *     interface to DerivedObject. (Note that this is only legal
     46  *     before DerivedObject's class_init; the results of
     47  *     g_type_interface_peek() are not allowed to change from one
     48  *     non-NULL vtable to another non-NULL vtable)
     49  */
     50 
     51 /*
     52  * BaseObject, a parent class for DerivedObject
     53  */
     54 #define BASE_TYPE_OBJECT          (base_object_get_type ())
     55 typedef struct _BaseObject        BaseObject;
     56 typedef struct _BaseObjectClass   BaseObjectClass;
     57 
     58 struct _BaseObject
     59 {
     60   GObject parent_instance;
     61 };
     62 struct _BaseObjectClass
     63 {
     64   GObjectClass parent_class;
     65 };
     66 
     67 static GType base_object_get_type ();
     68 static GType derived_object_get_type ();
     69 
     70 /*
     71  * DerivedObject, the child class of DerivedObject
     72  */
     73 #define DERIVED_TYPE_OBJECT          (derived_object_get_type ())
     74 typedef struct _DerivedObject        DerivedObject;
     75 typedef struct _DerivedObjectClass   DerivedObjectClass;
     76 
     77 struct _DerivedObject
     78 {
     79   BaseObject parent_instance;
     80 };
     81 struct _DerivedObjectClass
     82 {
     83   BaseObjectClass parent_class;
     84 };
     85 
     86 /*
     87  * The interfaces
     88  */
     89 typedef struct _TestIfaceClass TestIfaceClass;
     90 typedef struct _TestIfaceClass TestIface1Class;
     91 typedef struct _TestIfaceClass TestIface2Class;
     92 typedef struct _TestIfaceClass TestIface3Class;
     93 typedef struct _TestIfaceClass TestIface4Class;
     94 typedef struct _TestIfaceClass TestIface5Class;
     95 
     96 struct _TestIfaceClass
     97 {
     98   GTypeInterface base_iface;
     99   guint val;
    100 };
    101 
    102 #define TEST_TYPE_IFACE1 (test_iface1_get_type ())
    103 #define TEST_TYPE_IFACE2 (test_iface2_get_type ())
    104 #define TEST_TYPE_IFACE3 (test_iface3_get_type ())
    105 #define TEST_TYPE_IFACE4 (test_iface4_get_type ())
    106 #define TEST_TYPE_IFACE5 (test_iface5_get_type ())
    107 
    108 static DEFINE_IFACE (TestIface1, test_iface1,  NULL, NULL)
    109 static DEFINE_IFACE (TestIface2, test_iface2,  NULL, NULL)
    110 static DEFINE_IFACE (TestIface3, test_iface3,  NULL, NULL)
    111 static DEFINE_IFACE (TestIface4, test_iface4,  NULL, NULL)
    112 static DEFINE_IFACE (TestIface5, test_iface5,  NULL, NULL)
    113 
    114 static void
    115 add_interface (GType              object_type,
    116 	       GType              iface_type,
    117 	       GInterfaceInitFunc init_func)
    118 {
    119   GInterfaceInfo iface_info = {	NULL, NULL, NULL };
    120 
    121   iface_info.interface_init = init_func;
    122 
    123   g_type_add_interface_static (object_type, iface_type, &iface_info);
    124 }
    125 
    126 static void
    127 init_base_interface (TestIfaceClass *iface)
    128 {
    129   iface->val = 21;
    130 }
    131 
    132 static void
    133 add_base_interface (GType object_type,
    134 		    GType iface_type)
    135 {
    136   add_interface (object_type, iface_type,
    137 		 (GInterfaceInitFunc)init_base_interface);
    138 }
    139 
    140 static gboolean
    141 interface_is_base (GType object_type,
    142 		   GType iface_type)
    143 {
    144   gpointer g_class = g_type_class_peek (object_type);
    145   TestIfaceClass *iface = g_type_interface_peek (g_class, iface_type);
    146   return iface && iface->val == 21;
    147 }
    148 
    149 static void
    150 init_derived_interface (TestIfaceClass *iface)
    151 {
    152   iface->val = 42;
    153 }
    154 
    155 static void
    156 add_derived_interface (GType object_type,
    157 		       GType iface_type)
    158 {
    159   add_interface (object_type, iface_type,
    160 		 (GInterfaceInitFunc)init_derived_interface);
    161 }
    162 
    163 static gboolean
    164 interface_is_derived (GType object_type,
    165 		      GType iface_type)
    166 {
    167   gpointer g_class = g_type_class_peek (object_type);
    168   TestIfaceClass *iface = g_type_interface_peek (g_class, iface_type);
    169   return iface && iface->val == 42;
    170 }
    171 
    172 static void
    173 derived_object_class_init (BaseObjectClass *class)
    174 {
    175   add_base_interface (BASE_TYPE_OBJECT, TEST_TYPE_IFACE3);
    176 }
    177 
    178 static DEFINE_TYPE(BaseObject, base_object,
    179 		   NULL, NULL, NULL,
    180 		   G_TYPE_OBJECT)
    181 static DEFINE_TYPE(DerivedObject, derived_object,
    182 		   derived_object_class_init, NULL, NULL,
    183 		   BASE_TYPE_OBJECT)
    184 
    185 int
    186 main (int   argc,
    187       char *argv[])
    188 {
    189   g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
    190 			  G_LOG_LEVEL_WARNING |
    191 			  G_LOG_LEVEL_CRITICAL);
    192   g_type_init ();
    193 
    194   /* Register BaseObject */
    195   BASE_TYPE_OBJECT;
    196 
    197   add_base_interface (BASE_TYPE_OBJECT, TEST_TYPE_IFACE5);
    198 
    199   /* Class init BaseObject */
    200   g_type_class_ref (BASE_TYPE_OBJECT);
    201 
    202   add_base_interface (BASE_TYPE_OBJECT, TEST_TYPE_IFACE1);
    203 
    204   /* Register DerivedObject */
    205   DERIVED_TYPE_OBJECT;
    206 
    207   add_base_interface (BASE_TYPE_OBJECT, TEST_TYPE_IFACE2);
    208   add_derived_interface (DERIVED_TYPE_OBJECT, TEST_TYPE_IFACE5);
    209 
    210   /* Class init DerivedObject */
    211   g_type_class_ref (DERIVED_TYPE_OBJECT);
    212 
    213   add_base_interface (BASE_TYPE_OBJECT, TEST_TYPE_IFACE4);
    214 
    215   /* Check that all the non-overridden interfaces were properly inherited
    216    */
    217   g_assert (interface_is_base (DERIVED_TYPE_OBJECT, TEST_TYPE_IFACE1));
    218   g_assert (interface_is_base (DERIVED_TYPE_OBJECT, TEST_TYPE_IFACE2));
    219   g_assert (interface_is_base (DERIVED_TYPE_OBJECT, TEST_TYPE_IFACE3));
    220   g_assert (interface_is_base (DERIVED_TYPE_OBJECT, TEST_TYPE_IFACE4));
    221 
    222   /* Check that all the overridden interfaces were properly overridden
    223    */
    224   g_assert (interface_is_derived (DERIVED_TYPE_OBJECT, TEST_TYPE_IFACE5));
    225 
    226   return 0;
    227 }
    228