(root)/
glib-2.79.0/
gobject/
tests/
notify-init2.c
       1  /* GLib testing framework examples and tests
       2   * Copyright (C) 2022 Red Hat, Inc.
       3   *
       4   * SPDX-License-Identifier: LicenseRef-old-glib-tests
       5   *
       6   * This work is provided "as is"; redistribution and modification
       7   * in whole or in part, in any medium, physical or electronic is
       8   * permitted without restriction.
       9   *
      10   * This work is distributed in the hope that it will be useful,
      11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13   *
      14   * In no event shall the authors or contributors be liable for any
      15   * direct, indirect, incidental, special, exemplary, or consequential
      16   * damages (including, but not limited to, procurement of substitute
      17   * goods or services; loss of use, data, or profits; or business
      18   * interruption) however caused and on any theory of liability, whether
      19   * in contract, strict liability, or tort (including negligence or
      20   * otherwise) arising in any way out of the use of this software, even
      21   * if advised of the possibility of such damage.
      22   */
      23  
      24  #include <stdlib.h>
      25  #include <gstdio.h>
      26  #include <glib-object.h>
      27  
      28  typedef struct {
      29    GObject parent_instance;
      30    gint foo;
      31    gboolean bar;
      32    gchar *baz;
      33    gchar *quux;
      34  } TestObject;
      35  
      36  typedef struct {
      37    GObjectClass parent_class;
      38  } TestObjectClass;
      39  
      40  typedef enum {
      41    PROP_FOO = 1,
      42    PROP_BAR,
      43    PROP_BAZ,
      44    PROP_QUUX,
      45    N_PROPERTIES
      46  } TestObjectProperty;
      47  
      48  static GParamSpec *properties[N_PROPERTIES] = { NULL, };
      49  
      50  static GType test_object_get_type (void);
      51  G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
      52  
      53  static void
      54  test_object_set_foo (TestObject *obj,
      55                       gint        foo)
      56  {
      57    if (obj->foo != foo)
      58      {
      59        obj->foo = foo;
      60  
      61        g_assert (properties[PROP_FOO] != NULL);
      62        g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_FOO]);
      63      }
      64  }
      65  
      66  static void
      67  test_object_set_bar (TestObject *obj,
      68                       gboolean    bar)
      69  {
      70    bar = !!bar;
      71  
      72    if (obj->bar != bar)
      73      {
      74        obj->bar = bar;
      75  
      76        g_assert (properties[PROP_BAR] != NULL);
      77        g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_BAR]);
      78      }
      79  }
      80  
      81  static void
      82  test_object_set_baz (TestObject  *obj,
      83                       const gchar *baz)
      84  {
      85    if (g_strcmp0 (obj->baz, baz) != 0)
      86      {
      87        g_free (obj->baz);
      88        obj->baz = g_strdup (baz);
      89  
      90        g_assert (properties[PROP_BAZ] != NULL);
      91        g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_BAZ]);
      92      }
      93  }
      94  
      95  static void
      96  test_object_set_quux (TestObject  *obj,
      97                        const gchar *quux)
      98  {
      99    if (g_strcmp0 (obj->quux, quux) != 0)
     100      {
     101        g_free (obj->quux);
     102        obj->quux = g_strdup (quux);
     103  
     104        g_assert (properties[PROP_QUUX] != NULL);
     105        g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_QUUX]);
     106      }
     107  }
     108  
     109  static void
     110  test_object_finalize (GObject *gobject)
     111  {
     112    TestObject *self = (TestObject *) gobject;
     113  
     114    g_free (self->baz);
     115    g_free (self->quux);
     116  
     117    G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
     118  }
     119  
     120  static GObject *
     121  test_object_constructor (GType                  type,
     122                           guint                  n_construct_properties,
     123                           GObjectConstructParam *construct_properties)
     124  {
     125    return G_OBJECT_CLASS (test_object_parent_class)->constructor (type, n_construct_properties, construct_properties);
     126  }
     127  
     128  static void
     129  test_object_set_property (GObject *gobject,
     130                            guint prop_id,
     131                            const GValue *value,
     132                            GParamSpec *pspec)
     133  {
     134    TestObject *tobj = (TestObject *) gobject;
     135  
     136    g_assert_cmpint (prop_id, !=, 0);
     137    g_assert_true (prop_id < N_PROPERTIES && pspec == properties[prop_id]);
     138  
     139    switch ((TestObjectProperty)prop_id)
     140      {
     141      case PROP_FOO:
     142        test_object_set_foo (tobj, g_value_get_int (value));
     143        break;
     144  
     145      case PROP_BAR:
     146        test_object_set_bar (tobj, g_value_get_boolean (value));
     147        break;
     148  
     149      case PROP_BAZ:
     150        test_object_set_baz (tobj, g_value_get_string (value));
     151        break;
     152  
     153      case PROP_QUUX:
     154        test_object_set_quux (tobj, g_value_get_string (value));
     155        break;
     156  
     157      default:
     158        g_assert_not_reached ();
     159      }
     160  }
     161  
     162  static void
     163  test_object_get_property (GObject *gobject,
     164                            guint prop_id,
     165                            GValue *value,
     166                            GParamSpec *pspec)
     167  {
     168    TestObject *tobj = (TestObject *) gobject;
     169  
     170    g_assert_cmpint (prop_id, !=, 0);
     171    g_assert_true (prop_id < N_PROPERTIES && pspec == properties[prop_id]);
     172  
     173    switch ((TestObjectProperty)prop_id)
     174      {
     175      case PROP_FOO:
     176        g_value_set_int (value, tobj->foo);
     177        break;
     178  
     179      case PROP_BAR:
     180        g_value_set_boolean (value, tobj->bar);
     181        break;
     182  
     183      case PROP_BAZ:
     184        g_value_set_string (value, tobj->baz);
     185        break;
     186  
     187      case PROP_QUUX:
     188        g_value_set_string (value, tobj->quux);
     189        break;
     190  
     191      default:
     192        g_assert_not_reached ();
     193      }
     194  }
     195  
     196  static void
     197  test_object_class_init (TestObjectClass *klass)
     198  {
     199    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     200  
     201    properties[PROP_FOO] = g_param_spec_int ("foo", "Foo", "Foo",
     202                                             -1, G_MAXINT,
     203                                             0,
     204                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
     205    properties[PROP_BAR] = g_param_spec_boolean ("bar", "Bar", "Bar",
     206                                                 FALSE,
     207                                                 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
     208    properties[PROP_BAZ] = g_param_spec_string ("baz", "Baz", "Baz",
     209                                                NULL,
     210                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
     211  
     212    properties[PROP_QUUX] = g_param_spec_string ("quux", "quux", "quux",
     213                                                 NULL,
     214                                                 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
     215  
     216    gobject_class->constructor = test_object_constructor;
     217    gobject_class->set_property = test_object_set_property;
     218    gobject_class->get_property = test_object_get_property;
     219    gobject_class->finalize = test_object_finalize;
     220  
     221    g_object_class_install_properties (gobject_class, N_PROPERTIES, properties);
     222  }
     223  
     224  static void
     225  test_object_init (TestObject *self)
     226  {
     227    self->foo = 42;
     228    self->bar = TRUE;
     229    self->baz = g_strdup ("Hello");
     230  }
     231  
     232  static void
     233  test_notify_in_init (void)
     234  {
     235    TestObject *obj;
     236  
     237    g_test_summary ("Test that notify freezing during construction of objects with custom constructor works");
     238    g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2665");
     239  
     240    obj = g_object_new (test_object_get_type (), "bar", FALSE, NULL);
     241  
     242    g_object_unref (obj);
     243  }
     244  
     245  int
     246  main (int argc, char *argv[])
     247  {
     248    g_test_init (&argc, &argv, NULL);
     249  
     250    g_test_add_func ("/properties/notify-in-init2", test_notify_in_init);
     251  
     252    return g_test_run ();
     253  }