Branch data Line data Source code
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 : 3 : G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
52 : :
53 : : static void
54 : 1 : test_object_set_foo (TestObject *obj,
55 : : gint foo)
56 : : {
57 : 1 : if (obj->foo != foo)
58 : : {
59 : 1 : obj->foo = foo;
60 : :
61 : 1 : g_assert (properties[PROP_FOO] != NULL);
62 : 1 : g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_FOO]);
63 : : }
64 : 1 : }
65 : :
66 : : static void
67 : 1 : test_object_set_bar (TestObject *obj,
68 : : gboolean bar)
69 : : {
70 : 1 : bar = !!bar;
71 : :
72 : 1 : if (obj->bar != bar)
73 : : {
74 : 1 : obj->bar = bar;
75 : :
76 : 1 : g_assert (properties[PROP_BAR] != NULL);
77 : 1 : g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_BAR]);
78 : : }
79 : 1 : }
80 : :
81 : : static void
82 : 0 : test_object_set_baz (TestObject *obj,
83 : : const gchar *baz)
84 : : {
85 : 0 : if (g_strcmp0 (obj->baz, baz) != 0)
86 : : {
87 : 0 : g_free (obj->baz);
88 : 0 : obj->baz = g_strdup (baz);
89 : :
90 : 0 : g_assert (properties[PROP_BAZ] != NULL);
91 : 0 : g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_BAZ]);
92 : : }
93 : 0 : }
94 : :
95 : : static void
96 : 0 : test_object_set_quux (TestObject *obj,
97 : : const gchar *quux)
98 : : {
99 : 0 : if (g_strcmp0 (obj->quux, quux) != 0)
100 : : {
101 : 0 : g_free (obj->quux);
102 : 0 : obj->quux = g_strdup (quux);
103 : :
104 : 0 : g_assert (properties[PROP_QUUX] != NULL);
105 : 0 : g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_QUUX]);
106 : : }
107 : 0 : }
108 : :
109 : : static void
110 : 1 : test_object_finalize (GObject *gobject)
111 : : {
112 : 1 : TestObject *self = (TestObject *) gobject;
113 : :
114 : 1 : g_free (self->baz);
115 : 1 : g_free (self->quux);
116 : :
117 : 1 : G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
118 : 1 : }
119 : :
120 : : static GObject *
121 : 1 : test_object_constructor (GType type,
122 : : guint n_construct_properties,
123 : : GObjectConstructParam *construct_properties)
124 : : {
125 : 1 : return G_OBJECT_CLASS (test_object_parent_class)->constructor (type, n_construct_properties, construct_properties);
126 : : }
127 : :
128 : : static void
129 : 2 : test_object_set_property (GObject *gobject,
130 : : guint prop_id,
131 : : const GValue *value,
132 : : GParamSpec *pspec)
133 : : {
134 : 2 : TestObject *tobj = (TestObject *) gobject;
135 : :
136 : 2 : g_assert_cmpint (prop_id, !=, 0);
137 : 2 : g_assert_true (prop_id < N_PROPERTIES && pspec == properties[prop_id]);
138 : :
139 : 2 : switch ((TestObjectProperty)prop_id)
140 : : {
141 : 1 : case PROP_FOO:
142 : 1 : test_object_set_foo (tobj, g_value_get_int (value));
143 : 1 : break;
144 : :
145 : 1 : case PROP_BAR:
146 : 1 : test_object_set_bar (tobj, g_value_get_boolean (value));
147 : 1 : break;
148 : :
149 : 0 : case PROP_BAZ:
150 : 0 : test_object_set_baz (tobj, g_value_get_string (value));
151 : 0 : break;
152 : :
153 : 0 : case PROP_QUUX:
154 : 0 : test_object_set_quux (tobj, g_value_get_string (value));
155 : 0 : break;
156 : :
157 : 0 : default:
158 : : g_assert_not_reached ();
159 : : }
160 : 2 : }
161 : :
162 : : static void
163 : 0 : test_object_get_property (GObject *gobject,
164 : : guint prop_id,
165 : : GValue *value,
166 : : GParamSpec *pspec)
167 : : {
168 : 0 : TestObject *tobj = (TestObject *) gobject;
169 : :
170 : 0 : g_assert_cmpint (prop_id, !=, 0);
171 : 0 : g_assert_true (prop_id < N_PROPERTIES && pspec == properties[prop_id]);
172 : :
173 : 0 : switch ((TestObjectProperty)prop_id)
174 : : {
175 : 0 : case PROP_FOO:
176 : 0 : g_value_set_int (value, tobj->foo);
177 : 0 : break;
178 : :
179 : 0 : case PROP_BAR:
180 : 0 : g_value_set_boolean (value, tobj->bar);
181 : 0 : break;
182 : :
183 : 0 : case PROP_BAZ:
184 : 0 : g_value_set_string (value, tobj->baz);
185 : 0 : break;
186 : :
187 : 0 : case PROP_QUUX:
188 : 0 : g_value_set_string (value, tobj->quux);
189 : 0 : break;
190 : :
191 : 0 : default:
192 : : g_assert_not_reached ();
193 : : }
194 : 0 : }
195 : :
196 : : static void
197 : 1 : test_object_class_init (TestObjectClass *klass)
198 : : {
199 : 1 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
200 : :
201 : 1 : 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 : 1 : properties[PROP_BAR] = g_param_spec_boolean ("bar", "Bar", "Bar",
206 : : FALSE,
207 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
208 : 1 : properties[PROP_BAZ] = g_param_spec_string ("baz", "Baz", "Baz",
209 : : NULL,
210 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
211 : :
212 : 1 : 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 : 1 : gobject_class->constructor = test_object_constructor;
217 : 1 : gobject_class->set_property = test_object_set_property;
218 : 1 : gobject_class->get_property = test_object_get_property;
219 : 1 : gobject_class->finalize = test_object_finalize;
220 : :
221 : 1 : g_object_class_install_properties (gobject_class, N_PROPERTIES, properties);
222 : 1 : }
223 : :
224 : : static void
225 : 1 : test_object_init (TestObject *self)
226 : : {
227 : 1 : self->foo = 42;
228 : 1 : self->bar = TRUE;
229 : 1 : self->baz = g_strdup ("Hello");
230 : 1 : }
231 : :
232 : : static void
233 : 1 : test_notify_in_init (void)
234 : : {
235 : : TestObject *obj;
236 : :
237 : 1 : g_test_summary ("Test that notify freezing during construction of objects with custom constructor works");
238 : 1 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2665");
239 : :
240 : 1 : obj = g_object_new (test_object_get_type (), "bar", FALSE, NULL);
241 : :
242 : 1 : g_object_unref (obj);
243 : 1 : }
244 : :
245 : : int
246 : 1 : main (int argc, char *argv[])
247 : : {
248 : 1 : g_test_init (&argc, &argv, NULL);
249 : :
250 : 1 : g_test_add_func ("/properties/notify-in-init2", test_notify_in_init);
251 : :
252 : 1 : return g_test_run ();
253 : : }
|