From 7a4560e052f50c6f2ffa5287202abdb517716683 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 10 Jun 2022 13:48:40 +0100 Subject: [PATCH 1/4] tests: Port GObject singleton test to GTest framework Signed-off-by: Philip Withnall --- gobject/tests/singleton.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/gobject/tests/singleton.c b/gobject/tests/singleton.c index db024f18c..c5e151dbf 100644 --- a/gobject/tests/singleton.c +++ b/gobject/tests/singleton.c @@ -67,10 +67,8 @@ my_singleton_class_init (MySingletonClass *klass) G_OBJECT_CLASS (klass)->constructor = my_singleton_constructor; } -/* --- test program --- */ -int -main (int argc, - char *argv[]) +static void +test_singleton_construction (void) { MySingleton *singleton, *obj; @@ -85,5 +83,15 @@ main (int argc, /* shutdown */ g_object_unref (singleton); - return 0; +} + +int +main (int argc, + char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/gobject/singleton/construction", test_singleton_construction); + + return g_test_run (); } From 9af0444b9269650a39f47d179aaa9ffe61aace72 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 10 Jun 2022 13:52:37 +0100 Subject: [PATCH 2/4] tests: Simplify singleton test code using G_DECLARE_FINAL_TYPE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This doesn’t functionally change the test, just drops some boilerplate. Signed-off-by: Philip Withnall --- gobject/tests/singleton.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/gobject/tests/singleton.c b/gobject/tests/singleton.c index c5e151dbf..faebd23de 100644 --- a/gobject/tests/singleton.c +++ b/gobject/tests/singleton.c @@ -18,27 +18,14 @@ #include /* --- MySingleton class --- */ -typedef struct { + +struct _MySingleton { GObject parent_instance; -} MySingleton; -typedef struct { - GObjectClass parent_class; -} MySingletonClass; +}; -static GType my_singleton_get_type (void); -#define MY_TYPE_SINGLETON (my_singleton_get_type ()) -#define MY_SINGLETON(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), MY_TYPE_SINGLETON, MySingleton)) -#define MY_IS_SINGLETON(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), MY_TYPE_SINGLETON)) -#define MY_SINGLETON_CLASS(c) \ - (G_TYPE_CHECK_CLASS_CAST ((c), MY_TYPE_SINGLETON, MySingletonClass)) -#define MY_IS_SINGLETON_CLASS(c) \ - (G_TYPE_CHECK_CLASS_TYPE ((c), MY_TYPE_SINGLETON)) -#define MY_SINGLETON_GET_CLASS(o) \ - (G_TYPE_INSTANCE_GET_CLASS ((o), MY_TYPE_SINGLETON, MySingletonClass)) - -G_DEFINE_TYPE (MySingleton, my_singleton, G_TYPE_OBJECT) +#define MY_TYPE_SINGLETON my_singleton_get_type () +G_DECLARE_FINAL_TYPE (MySingleton, my_singleton, MY, SINGLETON, GObject) +G_DEFINE_FINAL_TYPE (MySingleton, my_singleton, G_TYPE_OBJECT) static MySingleton *the_one_and_only = NULL; From 12152788f9d26164855ab4127f1c204692695aa3 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 9 Jun 2022 11:34:39 -0400 Subject: [PATCH 3/4] tests: Add a singleton construct-property test Beef up the singleton testcase to reproduce a freeze count underflow when setting properties at construction time, with a custom constructor. Helps: #2666 --- gobject/tests/singleton.c | 65 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/gobject/tests/singleton.c b/gobject/tests/singleton.c index faebd23de..cc7dc52c7 100644 --- a/gobject/tests/singleton.c +++ b/gobject/tests/singleton.c @@ -21,6 +21,7 @@ struct _MySingleton { GObject parent_instance; + int myint; }; #define MY_TYPE_SINGLETON my_singleton_get_type () @@ -41,6 +42,15 @@ my_singleton_constructor (GType type, return G_OBJECT_CLASS (my_singleton_parent_class)->constructor (type, n_construct_properties, construct_properties); } +static void +my_singleton_finalize (GObject *object) +{ + g_assert ((GObject *) the_one_and_only == object); + the_one_and_only = NULL; + + G_OBJECT_CLASS (my_singleton_parent_class)->finalize (object); +} + static void my_singleton_init (MySingleton *self) { @@ -48,10 +58,46 @@ my_singleton_init (MySingleton *self) the_one_and_only = self; } +static void +my_singleton_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MySingleton *self = (MySingleton *) gobject; + + g_assert (prop_id == 1); + + self->myint = g_value_get_int (value); +} + +static void +my_singleton_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MySingleton *self = (MySingleton *) gobject; + + g_assert (prop_id == 1); + + g_value_set_int (value, self->myint); +} + static void my_singleton_class_init (MySingletonClass *klass) { - G_OBJECT_CLASS (klass)->constructor = my_singleton_constructor; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructor = my_singleton_constructor; + object_class->finalize = my_singleton_finalize; + object_class->set_property = my_singleton_set_property; + object_class->get_property = my_singleton_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), 1, + g_param_spec_int ("foo", NULL, NULL, + 0, G_MAXINT, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); } static void @@ -72,6 +118,22 @@ test_singleton_construction (void) g_object_unref (singleton); } +static void +test_singleton_construct_property (void) +{ + MySingleton *singleton; + + g_test_summary ("Test that creating a singleton with a construct-time property works"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2666"); + + /* create the singleton and set a property at construction time */ + singleton = g_object_new (MY_TYPE_SINGLETON, "foo", 1, NULL); + g_assert_nonnull (singleton); + + /* shutdown */ + g_object_unref (singleton); +} + int main (int argc, char *argv[]) @@ -79,6 +141,7 @@ main (int argc, g_test_init (&argc, &argv, NULL); g_test_add_func ("/gobject/singleton/construction", test_singleton_construction); + g_test_add_func ("/gobject/singleton/construct-property", test_singleton_construct_property); return g_test_run (); } From 98bd4eabf28474ff0af35c8d63064a59a782c371 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 8 Jun 2022 13:29:38 -0400 Subject: [PATCH 4/4] gobject: Don't thaw excessively We need to match the conditions in g_object_init for when we already have a freeze. Without that, we underflow the freeze count and trigger a warning. Fixes: #2666 --- gobject/gobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gobject/gobject.c b/gobject/gobject.c index f19c40180..e71547c19 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -2128,7 +2128,7 @@ g_object_new_with_custom_constructor (GObjectClass *class, /* Remember: if it was newly_constructed then g_object_init() * already did a freeze, so we now have two. Release one. */ - if (newly_constructed) + if (newly_constructed && CLASS_HAS_NOTIFY (class)) g_object_notify_queue_thaw (object, nqueue); }