#include #include #include typedef struct _TestObject { GObject parent_instance; gint foo; gboolean bar; gchar *baz; } TestObject; typedef struct _TestObjectClass { GObjectClass parent_class; } TestObjectClass; enum { PROP_0, PROP_FOO, PROP_BAR, PROP_BAZ, N_PROPERTIES }; static GParamSpec *properties[N_PROPERTIES] = { NULL, }; G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT); static void test_object_set_foo (TestObject *obj, gint foo) { if (obj->foo != foo) { obj->foo = foo; g_assert (properties[PROP_FOO] != NULL); g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_FOO]); } } static void test_object_set_bar (TestObject *obj, gboolean bar) { bar = !!bar; if (obj->bar != bar) { obj->bar = bar; g_assert (properties[PROP_BAR] != NULL); g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_BAR]); } } static void test_object_set_baz (TestObject *obj, const gchar *baz) { if (g_strcmp0 (obj->baz, baz) != 0) { g_free (obj->baz); obj->baz = g_strdup (baz); g_assert (properties[PROP_BAZ] != NULL); g_object_notify_by_pspec (G_OBJECT (obj), properties[PROP_BAZ]); } } static void test_object_finalize (GObject *gobject) { g_free (((TestObject *) gobject)->baz); G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject); } static void test_object_set_property (GObject *gobject, guint prop_id, const GValue *value, GParamSpec *pspec) { TestObject *tobj = (TestObject *) gobject; g_assert_cmpint (prop_id, !=, 0); g_assert_cmpint (prop_id, !=, N_PROPERTIES); g_assert (pspec == properties[prop_id]); switch (prop_id) { case PROP_FOO: test_object_set_foo (tobj, g_value_get_int (value)); break; case PROP_BAR: test_object_set_bar (tobj, g_value_get_boolean (value)); break; case PROP_BAZ: test_object_set_baz (tobj, g_value_get_string (value)); break; default: g_assert_not_reached (); } } static void test_object_get_property (GObject *gobject, guint prop_id, GValue *value, GParamSpec *pspec) { TestObject *tobj = (TestObject *) gobject; g_assert_cmpint (prop_id, !=, 0); g_assert_cmpint (prop_id, !=, N_PROPERTIES); g_assert (pspec == properties[prop_id]); switch (prop_id) { case PROP_FOO: g_value_set_int (value, tobj->foo); break; case PROP_BAR: g_value_set_boolean (value, tobj->bar); break; case PROP_BAZ: g_value_set_string (value, tobj->baz); break; default: g_assert_not_reached (); } } static void test_object_class_init (TestObjectClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); properties[PROP_FOO] = g_param_spec_int ("foo", "Foo", "Foo", -1, G_MAXINT, 0, G_PARAM_READWRITE); properties[PROP_BAR] = g_param_spec_boolean ("bar", "Bar", "Bar", FALSE, G_PARAM_READWRITE); properties[PROP_BAZ] = g_param_spec_string ("baz", "Baz", "Baz", NULL, G_PARAM_READWRITE); gobject_class->set_property = test_object_set_property; gobject_class->get_property = test_object_get_property; gobject_class->finalize = test_object_finalize; g_object_class_install_properties (gobject_class, N_PROPERTIES, properties); } static void test_object_init (TestObject *self) { self->foo = 42; self->bar = TRUE; self->baz = g_strdup ("Hello"); } static void properties_install (void) { TestObject *obj = g_object_new (test_object_get_type (), NULL); GParamSpec *pspec; g_assert (properties[PROP_FOO] != NULL); pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (obj), "foo"); g_assert (properties[PROP_FOO] == pspec); g_object_unref (obj); } typedef struct { const gchar *name; GParamSpec *pspec; } TestNotifyClosure; static void on_notify (GObject *gobject, GParamSpec *pspec, TestNotifyClosure *clos) { g_assert (clos->pspec == pspec); g_assert_cmpstr (clos->name, ==, pspec->name); } static void properties_notify (void) { TestObject *obj = g_object_new (test_object_get_type (), NULL); TestNotifyClosure clos; g_assert (properties[PROP_FOO] != NULL); clos.name = "foo"; clos.pspec = properties[PROP_FOO]; g_signal_connect (obj, "notify", G_CALLBACK (on_notify), &clos); g_object_set (obj, "foo", 47, NULL); g_object_unref (obj); } static void properties_construct (void) { TestObject *obj; gint val; g_test_bug ("630357"); /* more than 16 args triggers a realloc in g_object_new_valist() */ obj = g_object_new (test_object_get_type (), "foo", 1, "foo", 2, "foo", 3, "foo", 4, "foo", 5, "foo", 6, "foo", 7, "foo", 8, "foo", 9, "foo", 10, "foo", 11, "foo", 12, "foo", 13, "foo", 14, "foo", 15, "foo", 16, "foo", 17, "foo", 18, NULL); g_object_get (obj, "foo", &val, NULL); g_assert (val == 18); g_object_unref (obj); } int main (int argc, char *argv[]) { g_type_init (); g_test_init (&argc, &argv, NULL); g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/properties/install", properties_install); g_test_add_func ("/properties/notify", properties_notify); g_test_add_func ("/properties/construct", properties_construct); return g_test_run (); }