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 ())
55typedef struct _BaseObject        BaseObject;
56typedef struct _BaseObjectClass   BaseObjectClass;
57
58struct _BaseObject
59{
60  GObject parent_instance;
61};
62struct _BaseObjectClass
63{
64  GObjectClass parent_class;
65};
66
67static GType base_object_get_type ();
68static GType derived_object_get_type ();
69
70/*
71 * DerivedObject, the child class of DerivedObject
72 */
73#define DERIVED_TYPE_OBJECT          (derived_object_get_type ())
74typedef struct _DerivedObject        DerivedObject;
75typedef struct _DerivedObjectClass   DerivedObjectClass;
76
77struct _DerivedObject
78{
79  BaseObject parent_instance;
80};
81struct _DerivedObjectClass
82{
83  BaseObjectClass parent_class;
84};
85
86/*
87 * The interfaces
88 */
89typedef struct _TestIfaceClass TestIfaceClass;
90typedef struct _TestIfaceClass TestIface1Class;
91typedef struct _TestIfaceClass TestIface2Class;
92typedef struct _TestIfaceClass TestIface3Class;
93typedef struct _TestIfaceClass TestIface4Class;
94typedef struct _TestIfaceClass TestIface5Class;
95
96struct _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
108static DEFINE_IFACE (TestIface1, test_iface1,  NULL, NULL)
109static DEFINE_IFACE (TestIface2, test_iface2,  NULL, NULL)
110static DEFINE_IFACE (TestIface3, test_iface3,  NULL, NULL)
111static DEFINE_IFACE (TestIface4, test_iface4,  NULL, NULL)
112static DEFINE_IFACE (TestIface5, test_iface5,  NULL, NULL)
113
114static void
115add_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
126static void
127init_base_interface (TestIfaceClass *iface)
128{
129  iface->val = 21;
130}
131
132static void
133add_base_interface (GType object_type,
134		    GType iface_type)
135{
136  add_interface (object_type, iface_type,
137		 (GInterfaceInitFunc)init_base_interface);
138}
139
140static gboolean
141interface_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
149static void
150init_derived_interface (TestIfaceClass *iface)
151{
152  iface->val = 42;
153}
154
155static void
156add_derived_interface (GType object_type,
157		       GType iface_type)
158{
159  add_interface (object_type, iface_type,
160		 (GInterfaceInitFunc)init_derived_interface);
161}
162
163static gboolean
164interface_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
172static void
173derived_object_class_init (BaseObjectClass *class)
174{
175  add_base_interface (BASE_TYPE_OBJECT, TEST_TYPE_IFACE3);
176}
177
178static DEFINE_TYPE(BaseObject, base_object,
179		   NULL, NULL, NULL,
180		   G_TYPE_OBJECT)
181static DEFINE_TYPE(DerivedObject, derived_object,
182		   derived_object_class_init, NULL, NULL,
183		   BASE_TYPE_OBJECT)
184
185int
186main (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