(root)/
glib-2.79.0/
gobject/
tests/
override.c
       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   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   *
       8   * This library is free software; you can redistribute it and/or
       9   * modify it under the terms of the GNU Lesser General Public
      10   * License as published by the Free Software Foundation; either
      11   * version 2.1 of the License, or (at your option) any later version.
      12   *
      13   * This library is distributed in the hope that it will be useful,
      14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16   * Lesser General Public License for more details.
      17   *
      18   * You should have received a copy of the GNU Lesser General
      19   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      20   */
      21  
      22  #include <glib.h>
      23  #include <glib-object.h>
      24  
      25  #include "testcommon.h"
      26  
      27  static guint foo_signal_id = 0;
      28  static guint bar_signal_id = 0;
      29  static guint baz_signal_id = 0;
      30  
      31  static GType test_i_get_type (void);
      32  static GType test_a_get_type (void);
      33  static GType test_b_get_type (void);
      34  static GType test_c_get_type (void);
      35  
      36  static void  record (const gchar *str);
      37  
      38  #define TEST_TYPE_I (test_i_get_type ())
      39  
      40  typedef struct _TestI TestI;
      41  typedef struct _TestIClass TestIClass;
      42  
      43  struct _TestIClass
      44  {
      45    GTypeInterface base_iface;
      46  };
      47  
      48  static void
      49  test_i_foo (TestI *self)
      50  {
      51    record ("TestI::foo");
      52  }
      53  
      54  static void
      55  test_i_default_init (gpointer g_class)
      56  {
      57    foo_signal_id = g_signal_newv ("foo",
      58                                   TEST_TYPE_I,
      59                                   G_SIGNAL_RUN_LAST,
      60                                   g_cclosure_new(G_CALLBACK(test_i_foo),
      61                                                  NULL, NULL),
      62                                   NULL, NULL,
      63                                   g_cclosure_marshal_VOID__VOID,
      64                                   G_TYPE_NONE, 0, NULL);
      65  }
      66  
      67  static DEFINE_IFACE (TestI, test_i, NULL, test_i_default_init)
      68  
      69  #define TEST_TYPE_A (test_a_get_type())
      70  
      71       typedef struct _TestA TestA;
      72       typedef struct _TestAClass TestAClass;
      73  
      74  struct _TestA {
      75    GObject parent;
      76  };
      77  struct _TestAClass {
      78    GObjectClass parent_class;
      79  
      80    void (* bar) (TestA *self);
      81  };
      82  
      83  static void
      84  test_a_foo (TestI *self)
      85  {
      86    GValue args[1] = { G_VALUE_INIT };
      87  
      88    record ("TestA::foo");
      89  
      90    g_value_init (&args[0], TEST_TYPE_A);
      91    g_value_set_object (&args[0], self);
      92  
      93    g_assert_cmpint (g_signal_get_invocation_hint (self)->signal_id,
      94                     ==,
      95                     foo_signal_id);
      96    g_signal_chain_from_overridden (args, NULL);
      97  
      98    g_value_unset (&args[0]);
      99  }
     100  
     101  static void
     102  test_a_bar (TestA *self)
     103  {
     104    record ("TestA::bar");
     105  }
     106  
     107  static gchar *
     108  test_a_baz (TestA    *self,
     109              GObject  *object,
     110              gpointer  pointer)
     111  {
     112    record ("TestA::baz");
     113  
     114    g_assert_true (object == G_OBJECT (self));
     115    g_assert_cmpint (GPOINTER_TO_INT (pointer), ==, 23);
     116  
     117    return g_strdup ("TestA::baz");
     118  }
     119  
     120  static void
     121  test_a_class_init (TestAClass *class)
     122  {
     123    class->bar = test_a_bar;
     124  
     125    bar_signal_id = g_signal_new ("bar",
     126                                  TEST_TYPE_A,
     127                                  G_SIGNAL_RUN_LAST,
     128                                  G_STRUCT_OFFSET (TestAClass, bar),
     129                                  NULL, NULL,
     130                                  g_cclosure_marshal_VOID__VOID,
     131                                  G_TYPE_NONE, 0, NULL);
     132  
     133    baz_signal_id =
     134      g_signal_new_class_handler ("baz",
     135                                  TEST_TYPE_A,
     136                                  G_SIGNAL_RUN_LAST,
     137                                  G_CALLBACK (test_a_baz),
     138                                  NULL, NULL,
     139                                  g_cclosure_marshal_STRING__OBJECT_POINTER,
     140                                  G_TYPE_STRING, 2,
     141                                  G_TYPE_OBJECT,
     142                                  G_TYPE_POINTER);
     143  }
     144  
     145  static void
     146  test_a_interface_init (TestIClass *iface)
     147  {
     148    g_signal_override_class_closure (foo_signal_id,
     149                                     TEST_TYPE_A,
     150                                     g_cclosure_new (G_CALLBACK (test_a_foo),
     151                                                     NULL, NULL));
     152  }
     153  
     154  static DEFINE_TYPE_FULL (TestA, test_a,
     155                           test_a_class_init, NULL, NULL,
     156                           G_TYPE_OBJECT,
     157                           INTERFACE (test_a_interface_init, TEST_TYPE_I))
     158  
     159  #define TEST_TYPE_B (test_b_get_type())
     160  
     161  typedef struct _TestB TestB;
     162  typedef struct _TestBClass TestBClass;
     163  
     164  struct _TestB {
     165    TestA parent;
     166  };
     167  struct _TestBClass {
     168    TestAClass parent_class;
     169  };
     170  
     171  static void
     172  test_b_foo (TestI *self)
     173  {
     174    GValue args[1] = { G_VALUE_INIT };
     175  
     176    record ("TestB::foo");
     177  
     178    g_value_init (&args[0], TEST_TYPE_A);
     179    g_value_set_object (&args[0], self);
     180  
     181    g_assert_cmpint (g_signal_get_invocation_hint (self)->signal_id,
     182                     ==,
     183                     foo_signal_id);
     184    g_signal_chain_from_overridden (args, NULL);
     185  
     186    g_value_unset (&args[0]);
     187  }
     188  
     189  static void
     190  test_b_bar (TestA *self)
     191  {
     192    GValue args[1] = { G_VALUE_INIT };
     193  
     194    record ("TestB::bar");
     195  
     196    g_value_init (&args[0], TEST_TYPE_A);
     197    g_value_set_object (&args[0], self);
     198  
     199    g_assert_cmpint (g_signal_get_invocation_hint (self)->signal_id,
     200                     ==,
     201                     bar_signal_id);
     202    g_signal_chain_from_overridden (args, NULL);
     203  
     204    g_value_unset (&args[0]);
     205  }
     206  
     207  static gchar *
     208  test_b_baz (TestA    *self,
     209              GObject  *object,
     210              gpointer  pointer)
     211  {
     212    gchar *retval = NULL;
     213  
     214    record ("TestB::baz");
     215  
     216    g_assert_true (object == G_OBJECT (self));
     217    g_assert_cmpint (GPOINTER_TO_INT (pointer), ==, 23);
     218  
     219    g_signal_chain_from_overridden_handler (self, object, pointer, &retval);
     220  
     221    if (retval)
     222      {
     223        gchar *tmp = g_strconcat (retval , ",TestB::baz", NULL);
     224        g_free (retval);
     225        retval = tmp;
     226      }
     227  
     228    return retval;
     229  }
     230  
     231  static void
     232  test_b_class_init (TestBClass *class)
     233  {
     234    g_signal_override_class_closure (foo_signal_id,
     235                                     TEST_TYPE_B,
     236                                     g_cclosure_new (G_CALLBACK (test_b_foo),
     237                                                     NULL, NULL));
     238    g_signal_override_class_closure (bar_signal_id,
     239                                     TEST_TYPE_B,
     240                                     g_cclosure_new (G_CALLBACK (test_b_bar),
     241                                                     NULL, NULL));
     242    g_signal_override_class_handler ("baz",
     243                                     TEST_TYPE_B,
     244                                     G_CALLBACK (test_b_baz));
     245  }
     246  
     247  static DEFINE_TYPE (TestB, test_b,
     248                      test_b_class_init, NULL, NULL,
     249                      TEST_TYPE_A)
     250  
     251  #define TEST_TYPE_C (test_c_get_type())
     252  
     253  typedef struct _TestC TestC;
     254  typedef struct _TestCClass TestCClass;
     255  
     256  struct _TestC {
     257    TestB parent;
     258  };
     259  struct _TestCClass {
     260    TestBClass parent_class;
     261  };
     262  
     263  static void
     264  test_c_foo (TestI *self)
     265  {
     266    GValue args[1] = { G_VALUE_INIT };
     267  
     268    record ("TestC::foo");
     269  
     270    g_value_init (&args[0], TEST_TYPE_A);
     271    g_value_set_object (&args[0], self);
     272  
     273    g_assert_cmpint (g_signal_get_invocation_hint (self)->signal_id,
     274                     ==,
     275                     foo_signal_id);
     276    g_signal_chain_from_overridden (args, NULL);
     277  
     278    g_value_unset (&args[0]);
     279  }
     280  
     281  static void
     282  test_c_bar (TestA *self)
     283  {
     284    GValue args[1] = { G_VALUE_INIT };
     285  
     286    record ("TestC::bar");
     287  
     288    g_value_init (&args[0], TEST_TYPE_A);
     289    g_value_set_object (&args[0], self);
     290  
     291    g_assert_cmpint (g_signal_get_invocation_hint (self)->signal_id,
     292                     ==,
     293                     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_true (object == G_OBJECT (self));
     309    g_assert_cmpint (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  
     346  static void
     347  record (const gchar *str)
     348  {
     349    if (test_string->len)
     350      g_string_append_c (test_string, ',');
     351    g_string_append (test_string, str);
     352  }
     353  
     354  static void
     355  test (GType        type,
     356        const gchar *signal,
     357        const gchar *expected,
     358        const gchar *expected_retval)
     359  {
     360    GObject *self = g_object_new (type, NULL);
     361  
     362    test_string = g_string_new (NULL);
     363  
     364    if (strcmp (signal, "baz"))
     365      {
     366        g_signal_emit_by_name (self, signal);
     367      }
     368    else
     369      {
     370        gchar *ret;
     371  
     372        g_signal_emit_by_name (self, signal, self, GINT_TO_POINTER (23), &ret);
     373        g_assert_cmpstr (ret, ==, expected_retval);
     374  
     375        g_free (ret);
     376      }
     377  
     378    g_test_message ("*** emitting %s on a %s instance\n"
     379                    "    Expecting: %s\n"
     380                    "    Got: %s",
     381                    signal, g_type_name (type),
     382                    expected,
     383                    test_string->str);
     384  
     385    g_assert_cmpstr (test_string->str, ==, expected);
     386  
     387    g_string_free (test_string, TRUE);
     388    g_object_unref (self);
     389  }
     390  
     391  static void
     392  test_override (void)
     393  {
     394    test (TEST_TYPE_A, "foo", "TestA::foo,TestI::foo", NULL);
     395    test (TEST_TYPE_A, "bar", "TestA::bar", NULL);
     396    test (TEST_TYPE_A, "baz", "TestA::baz", "TestA::baz");
     397  
     398    test (TEST_TYPE_B, "foo", "TestB::foo,TestA::foo,TestI::foo", NULL);
     399    test (TEST_TYPE_B, "bar", "TestB::bar,TestA::bar", NULL);
     400    test (TEST_TYPE_B, "baz", "TestB::baz,TestA::baz", "TestA::baz,TestB::baz");
     401  
     402    test (TEST_TYPE_C, "foo", "TestC::foo,TestB::foo,TestA::foo,TestI::foo", NULL);
     403    test (TEST_TYPE_C, "bar", "TestC::bar,TestB::bar,TestA::bar", NULL);
     404    test (TEST_TYPE_C, "baz", "TestC::baz,TestB::baz,TestA::baz", "TestA::baz,TestB::baz,TestC::baz");
     405  }
     406  
     407  int
     408  main (int  argc,
     409        char **argv)
     410  {
     411    g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
     412                            G_LOG_LEVEL_WARNING |
     413                            G_LOG_LEVEL_CRITICAL);
     414  
     415    g_test_init (&argc, &argv, NULL);
     416  
     417    g_test_add_func ("/gobject/override", test_override);
     418  
     419    return g_test_run ();
     420  }