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
38static guint foo_signal_id = 0;
39static guint bar_signal_id = 0;
40static guint baz_signal_id = 0;
41
42static GType test_i_get_type (void);
43static GType test_a_get_type (void);
44static GType test_b_get_type (void);
45static GType test_c_get_type (void);
46
47static void  record (const gchar *str);
48
49#define TEST_TYPE_I (test_i_get_type ())
50
51typedef struct _TestI TestI;
52typedef struct _TestIClass TestIClass;
53
54struct _TestIClass
55{
56  GTypeInterface base_iface;
57};
58
59static void
60test_i_foo (TestI *self)
61{
62  record ("TestI::foo");
63}
64
65static void
66test_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
78static 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
85struct _TestA {
86  GObject parent;
87};
88struct _TestAClass {
89  GObjectClass parent_class;
90
91  void (* bar) (TestA *self);
92};
93
94static void
95test_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
110static void
111test_a_bar (TestA *self)
112{
113  record ("TestA::bar");
114}
115
116static gchar *
117test_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
129static void
130test_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
153static void
154test_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
162static 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
169typedef struct _TestB TestB;
170typedef struct _TestBClass TestBClass;
171
172struct _TestB {
173  TestA parent;
174};
175struct _TestBClass {
176  TestAClass parent_class;
177};
178
179static void
180test_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
195static void
196test_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
211static gchar *
212test_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
235static void
236test_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
251static 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
257typedef struct _TestC TestC;
258typedef struct _TestCClass TestCClass;
259
260struct _TestC {
261  TestB parent;
262};
263struct _TestCClass {
264  TestBClass parent_class;
265};
266
267static void
268test_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
283static void
284test_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
299static gchar *
300test_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
323static void
324test_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
340static DEFINE_TYPE (TestC, test_c,
341		    test_c_class_init, NULL, NULL,
342		    TEST_TYPE_B)
343
344static GString *test_string = NULL;
345gboolean failed = FALSE;
346
347static void
348record (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
355static void
356test (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
397int
398main (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