From 0ccef79d7e9d1b19cdb10b3a147b64b41686905d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 9 Jul 2005 01:46:51 +0000 Subject: 2005-07-08 Colin Walters * test/glib/test-service-glib.xml: * test/glib/test-service-glib.c: * test/glib/test-dbus-glib.c: Test a{sv}. * glib/examples/statemachine/statemachine.c: * glib/examples/statemachine/statemachine-server.c: * glib/examples/statemachine/statemachine-client.c: Fix some bugs, add progress bar, etc. * glib/dbus-gvalue.c (register_array, register_dict): Delete; not needed anymore due to generic array/map marshalling. (dbus_g_value_types_init): Don't register basic arrays or the string/string hash. (dbus_gtype_from_signature_iter): Don't try to recurse into variants. (dbus_gtype_to_signature): Check collection/map before type metadata. (demarshal_garray_basic): Renamed to demarshal_collection_array. (demarshal_ghashtable): Renamed to demarshal_map; fix to use new generic map creation/append functions instead of hash table specifically. (get_type_demarshaller): Handle maps. (demarshal_collection): Dispatch on collection type to either demarshal_collection_ptrarray or demarshal_collection_array. (get_type_marshaller): Handle maps. (marshal_collection): Dispatch collection type to either marshal_collection_ptrarray or marshal_collection_array. (_dbus_gvalue_test): New test. * glib/dbus-gvalue-utils.c (unset_and_free_g_value): New function. (hash_free_from_gtype): Use it to free GValues. (hashtable_append): New function. (ptrarray_append): Fix prototype. (slist_append): Ditto. (_dbus_gvalue_utils_test): Extend tests. * glib/dbus-gtype-specialized.c (dbus_g_type_specialized_init_append): Renamed from dbus_g_type_specialized_collection_init_append. Remove const from value, since we steal it. (dbus_g_type_specialized_map_append): New function. * glib/dbus-gtype-specialized.h: Update prototypes. Add DBusGTypeSpecializedMapAppendFunc. * glib/dbus-gtest.c (dbus_glib_internal_do_not_use_run_tests): Run _dbus_gvalue_test. * glib/dbus-gtest.h: Prototype it. --- ChangeLog | 52 +++ glib/dbus-gtest.c | 4 + glib/dbus-gtest.h | 1 + glib/dbus-gtype-specialized.c | 13 +- glib/dbus-gtype-specialized.h | 15 +- glib/dbus-gvalue-utils.c | 116 ++++++- glib/dbus-gvalue.c | 402 ++++++++++++----------- glib/examples/statemachine/statemachine-client.c | 192 +++++++++-- glib/examples/statemachine/statemachine-server.c | 27 ++ glib/examples/statemachine/statemachine.c | 44 +-- test/glib/test-dbus-glib.c | 60 ++++ test/glib/test-service-glib.c | 34 ++ test/glib/test-service-glib.xml | 5 + 13 files changed, 706 insertions(+), 259 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9ad68040..f98a6e76 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,55 @@ +2005-07-08 Colin Walters + + * test/glib/test-service-glib.xml: + * test/glib/test-service-glib.c: + * test/glib/test-dbus-glib.c: Test a{sv}. + + * glib/examples/statemachine/statemachine.c: + * glib/examples/statemachine/statemachine-server.c: + * glib/examples/statemachine/statemachine-client.c: Fix some bugs, + add progress bar, etc. + + * glib/dbus-gvalue.c (register_array, register_dict): Delete; not + needed anymore due to generic array/map marshalling. + (dbus_g_value_types_init): Don't register basic arrays or the + string/string hash. + (dbus_gtype_from_signature_iter): Don't try to recurse into + variants. + (dbus_gtype_to_signature): Check collection/map before type + metadata. + (demarshal_garray_basic): Renamed to demarshal_collection_array. + (demarshal_ghashtable): Renamed to demarshal_map; fix to use new + generic map creation/append functions instead of hash table + specifically. + (get_type_demarshaller): Handle maps. + (demarshal_collection): Dispatch on collection type to either + demarshal_collection_ptrarray or demarshal_collection_array. + (get_type_marshaller): Handle maps. + (marshal_collection): Dispatch collection type to either + marshal_collection_ptrarray or marshal_collection_array. + (_dbus_gvalue_test): New test. + + * glib/dbus-gvalue-utils.c (unset_and_free_g_value): New function. + (hash_free_from_gtype): Use it to free GValues. + (hashtable_append): New function. + (ptrarray_append): Fix prototype. + (slist_append): Ditto. + (_dbus_gvalue_utils_test): Extend tests. + + * glib/dbus-gtype-specialized.c + (dbus_g_type_specialized_init_append): Renamed from + dbus_g_type_specialized_collection_init_append. Remove const from + value, since we steal it. + (dbus_g_type_specialized_map_append): New function. + + * glib/dbus-gtype-specialized.h: Update prototypes. + Add DBusGTypeSpecializedMapAppendFunc. + + * glib/dbus-gtest.c (dbus_glib_internal_do_not_use_run_tests): Run + _dbus_gvalue_test. + + * glib/dbus-gtest.h: Prototype it. + 2005-07-08 Ross Burton * dbus/dbus-glib.h: diff --git a/glib/dbus-gtest.c b/glib/dbus-gtest.c index 2b79feb4..e5c2e8b9 100644 --- a/glib/dbus-gtest.c +++ b/glib/dbus-gtest.c @@ -63,6 +63,10 @@ dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir) if (!_dbus_gvalue_utils_test (test_data_dir)) die ("gvalue utils"); + printf ("%s: running GValue tests\n", "dbus-glib-test"); + if (!_dbus_gvalue_test (test_data_dir)) + die ("gvalue utils"); + printf ("%s: running glib tests\n", "dbus-glib-test"); if (!_dbus_glib_test (test_data_dir)) die ("glib"); diff --git a/glib/dbus-gtest.h b/glib/dbus-gtest.h index 73bf0dda..75633ea7 100644 --- a/glib/dbus-gtest.h +++ b/glib/dbus-gtest.h @@ -30,6 +30,7 @@ gboolean _dbus_gmain_test (const char *test_data_dir); gboolean _dbus_gobject_test (const char *test_data_dir); gboolean _dbus_gutils_test (const char *test_data_dir); gboolean _dbus_glib_test (const char *test_data_dir); +gboolean _dbus_gvalue_test (const char *test_data_dir); gboolean _dbus_gvalue_utils_test (const char *test_data_dir); void dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir); diff --git a/glib/dbus-gtype-specialized.c b/glib/dbus-gtype-specialized.c index d588fa86..ccf65eef 100644 --- a/glib/dbus-gtype-specialized.c +++ b/glib/dbus-gtype-specialized.c @@ -427,7 +427,7 @@ typedef struct { } DBusGTypeSpecializedAppendContextReal; void -dbus_g_type_specialized_collection_init_append (GValue *value, DBusGTypeSpecializedAppendContext *ctx) +dbus_g_type_specialized_init_append (GValue *value, DBusGTypeSpecializedAppendContext *ctx) { DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx; GType gtype; @@ -446,7 +446,7 @@ dbus_g_type_specialized_collection_init_append (GValue *value, DBusGTypeSpeciali void dbus_g_type_specialized_collection_append (DBusGTypeSpecializedAppendContext *ctx, - const GValue *elt) + GValue *elt) { DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx; ((DBusGTypeSpecializedCollectionVtable *) realctx->specdata->klass->vtable)->append_func (ctx, elt); @@ -460,6 +460,15 @@ dbus_g_type_specialized_collection_end_append (DBusGTypeSpecializedAppendContext ((DBusGTypeSpecializedCollectionVtable *) realctx->specdata->klass->vtable)->end_append_func (ctx); } +void +dbus_g_type_specialized_map_append (DBusGTypeSpecializedAppendContext *ctx, + GValue *key, + GValue *val) +{ + DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx; + ((DBusGTypeSpecializedMapVtable *) realctx->specdata->klass->vtable)->append_func (ctx, key, val); +} + void dbus_g_type_map_value_iterate (const GValue *value, DBusGTypeSpecializedMapIterator iterator, diff --git a/glib/dbus-gtype-specialized.h b/glib/dbus-gtype-specialized.h index 8e47db98..e95af3e5 100644 --- a/glib/dbus-gtype-specialized.h +++ b/glib/dbus-gtype-specialized.h @@ -58,12 +58,17 @@ typedef struct { gpointer d; } DBusGTypeSpecializedAppendContext; -void dbus_g_type_specialized_collection_init_append (GValue *val, DBusGTypeSpecializedAppendContext *ctx); +void dbus_g_type_specialized_init_append (GValue *val, DBusGTypeSpecializedAppendContext *ctx); -void dbus_g_type_specialized_collection_append (DBusGTypeSpecializedAppendContext *ctx, const GValue *elt); +void dbus_g_type_specialized_collection_append (DBusGTypeSpecializedAppendContext *ctx, GValue *elt); void dbus_g_type_specialized_collection_end_append (DBusGTypeSpecializedAppendContext *ctx); +void dbus_g_type_specialized_map_append (DBusGTypeSpecializedAppendContext *ctx, + GValue *key, + GValue *val); + + gboolean dbus_g_type_collection_get_fixed (GValue *value, gpointer *data, guint *len); @@ -90,8 +95,8 @@ typedef struct { } DBusGTypeSpecializedVtable; typedef gboolean (*DBusGTypeSpecializedCollectionFixedAccessorFunc) (GType type, gpointer instance, gpointer *values, guint *len); -typedef void (*DBusGTypeSpecializedCollectionIteratorFunc) (GType type, gpointer instance, DBusGTypeSpecializedCollectionIterator iterator, gpointer user_data); -typedef void (*DBusGTypeSpecializedCollectionAppendFunc) (DBusGTypeSpecializedAppendContext *ctx, const GValue *val); +typedef void (*DBusGTypeSpecializedCollectionIteratorFunc) (GType type, gpointer instance, DBusGTypeSpecializedCollectionIterator iterator, gpointer user_data); +typedef void (*DBusGTypeSpecializedCollectionAppendFunc) (DBusGTypeSpecializedAppendContext *ctx, GValue *val); typedef void (*DBusGTypeSpecializedCollectionEndAppendFunc) (DBusGTypeSpecializedAppendContext *ctx); typedef struct { @@ -103,10 +108,12 @@ typedef struct { } DBusGTypeSpecializedCollectionVtable; typedef void (*DBusGTypeSpecializedMapIteratorFunc) (GType type, gpointer instance, DBusGTypeSpecializedMapIterator iterator, gpointer user_data); +typedef void (*DBusGTypeSpecializedMapAppendFunc) (DBusGTypeSpecializedAppendContext *ctx, GValue *key, GValue *val); typedef struct { DBusGTypeSpecializedVtable base_vtable; DBusGTypeSpecializedMapIteratorFunc iterator; + DBusGTypeSpecializedMapAppendFunc append_func; } DBusGTypeSpecializedMapVtable; void dbus_g_type_specialized_init (void); diff --git a/glib/dbus-gvalue-utils.c b/glib/dbus-gvalue-utils.c index b281f6ee..b17eee16 100644 --- a/glib/dbus-gvalue-utils.c +++ b/glib/dbus-gvalue-utils.c @@ -226,6 +226,15 @@ hash_func_from_gtype (GType gtype, GHashFunc *func) } } +static void +unset_and_free_g_value (gpointer val) +{ + GValue *value = val; + + g_value_unset (value); + g_free (value); +} + static gboolean hash_free_from_gtype (GType gtype, GDestroyNotify *func) { @@ -244,7 +253,7 @@ hash_free_from_gtype (GType gtype, GDestroyNotify *func) default: if (gtype == G_TYPE_VALUE) { - *func = (GDestroyNotify) g_value_unset; + *func = unset_and_free_g_value; return TRUE; } return FALSE; @@ -441,6 +450,17 @@ dbus_g_hash_table_insert_steal_values (GHashTable *table, g_hash_table_insert (table, key, val); } +static void +hashtable_append (DBusGTypeSpecializedAppendContext *ctx, + GValue *key, + GValue *val) +{ + GHashTable *table; + + table = g_value_get_boxed (ctx->val); + dbus_g_hash_table_insert_steal_values (table, key, val); +} + static gpointer hashtable_constructor (GType type) { @@ -667,7 +687,7 @@ ptrarray_copy (GType type, gpointer src) } static void -ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, const GValue *value) +ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value) { GPtrArray *array; @@ -740,7 +760,7 @@ slist_copy (GType type, gpointer src) } static void -slist_append (DBusGTypeSpecializedAppendContext *ctx, const GValue *value) +slist_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value) { GSList *list; @@ -822,7 +842,8 @@ dbus_g_type_specialized_builtins_init (void) NULL, NULL }, - hashtable_iterator + hashtable_iterator, + hashtable_append }; dbus_g_type_register_map ("GHashTable", &hashtable_vtable, 0); @@ -860,6 +881,35 @@ test_specialized_hash (const GValue *key, const GValue *val, gpointer user_data) } } +static void +test_specialized_hash_2 (const GValue *key, const GValue *val, gpointer user_data) +{ + TestSpecializedHashData *data = user_data; + const GValue *realval; + + g_assert (G_VALUE_HOLDS_STRING (key)); + g_assert (G_VALUE_TYPE (val) == G_TYPE_VALUE); + + realval = g_value_get_boxed (val); + + if (!strcmp (g_value_get_string (key), "foo")) + { + data->seen_foo = TRUE; + g_assert (G_VALUE_HOLDS_UINT (realval)); + g_assert (g_value_get_uint (realval) == 20); + } + else if (!strcmp (g_value_get_string (key), "baz")) + { + data->seen_baz = TRUE; + g_assert (G_VALUE_HOLDS_STRING (realval)); + g_assert (!strcmp ("bar", g_value_get_string (realval))); + } + else + { + g_assert_not_reached (); + } +} + gboolean _dbus_gvalue_utils_test (const char *datadir) { @@ -911,6 +961,62 @@ _dbus_gvalue_utils_test (const char *datadir) g_value_unset (&val); } + type = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE); + g_assert (dbus_g_type_is_map (type)); + g_assert (dbus_g_type_get_map_key_specialization (type) == G_TYPE_STRING); + g_assert (dbus_g_type_get_map_value_specialization (type) == G_TYPE_VALUE); + { + GHashTable *instance; + GValue val = { 0, }; + TestSpecializedHashData hashdata; + DBusGTypeSpecializedAppendContext ctx; + GValue *eltval; + + instance = dbus_g_type_specialized_construct (type); + g_value_init (&val, type); + g_value_set_boxed_take_ownership (&val, instance); + + dbus_g_type_specialized_init_append (&val, &ctx); + + { + GValue keyval = { 0, }; + GValue valval = { 0, }; + g_value_init (&keyval, G_TYPE_STRING); + g_value_set_string (&keyval, "foo"); + + g_value_init (&valval, G_TYPE_VALUE); + eltval = g_new0 (GValue, 1); + g_value_init (eltval, G_TYPE_UINT); + g_value_set_uint (eltval, 20); + g_value_set_boxed_take_ownership (&valval, eltval); + dbus_g_type_specialized_map_append (&ctx, &keyval, &valval); + } + + { + GValue keyval = { 0, }; + GValue valval = { 0, }; + g_value_init (&keyval, G_TYPE_STRING); + g_value_set_string (&keyval, "baz"); + g_value_init (&valval, G_TYPE_VALUE); + eltval = g_new0 (GValue, 1); + g_value_init (eltval, G_TYPE_STRING); + g_value_set_string (eltval, "bar"); + g_value_set_boxed_take_ownership (&valval, eltval); + dbus_g_type_specialized_map_append (&ctx, &keyval, &valval); + } + + hashdata.seen_foo = FALSE; + hashdata.seen_baz = FALSE; + dbus_g_type_map_value_iterate (&val, + test_specialized_hash_2, + &hashdata); + + g_assert (hashdata.seen_foo); + g_assert (hashdata.seen_baz); + + g_value_unset (&val); + } + type = dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING); g_assert (dbus_g_type_is_collection (type)); g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_STRING); @@ -927,7 +1033,7 @@ _dbus_gvalue_utils_test (const char *datadir) g_value_init (&val, type); g_value_set_boxed_take_ownership (&val, instance); - dbus_g_type_specialized_collection_init_append (&val, &ctx); + dbus_g_type_specialized_init_append (&val, &ctx); g_value_init (&eltval, G_TYPE_STRING); g_value_set_static_string (&eltval, "foo"); diff --git a/glib/dbus-gvalue.c b/glib/dbus-gvalue.c index 4e7495c7..88397731 100644 --- a/glib/dbus-gvalue.c +++ b/glib/dbus-gvalue.c @@ -22,6 +22,8 @@ * */ +#include "config.h" +#include "dbus-gtest.h" #include "dbus-gvalue.h" #include "dbus-gobject.h" #include "dbus-gvalue-utils.h" @@ -76,12 +78,6 @@ static gboolean demarshal_variant (DBusGValueMarshalCtx *cont DBusMessageIter *iter, GValue *value, GError **error); -static gboolean marshal_garray_basic (DBusMessageIter *iter, - const GValue *value); -static gboolean demarshal_garray_basic (DBusGValueMarshalCtx *context, - DBusMessageIter *iter, - GValue *value, - GError **error); static gboolean marshal_proxy (DBusMessageIter *iter, const GValue *value); static gboolean demarshal_proxy (DBusGValueMarshalCtx *context, @@ -102,17 +98,29 @@ static gboolean demarshal_object (DBusGValueMarshalCtx *cont GError **error); static gboolean marshal_map (DBusMessageIter *iter, const GValue *value); -static gboolean demarshal_ghashtable (DBusGValueMarshalCtx *context, +static gboolean demarshal_map (DBusGValueMarshalCtx *context, DBusMessageIter *iter, GValue *value, GError **error); static gboolean marshal_collection (DBusMessageIter *iter, const GValue *value); +static gboolean marshal_collection_ptrarray (DBusMessageIter *iter, + const GValue *value); +static gboolean marshal_collection_array (DBusMessageIter *iter, + const GValue *value); static gboolean demarshal_collection (DBusGValueMarshalCtx *context, DBusMessageIter *iter, GValue *value, GError **error); +static gboolean demarshal_collection_ptrarray (DBusGValueMarshalCtx *context, + DBusMessageIter *iter, + GValue *value, + GError **error); +static gboolean demarshal_collection_array (DBusGValueMarshalCtx *context, + DBusMessageIter *iter, + GValue *value, + GError **error); static gboolean marshal_recurse (DBusMessageIter *iter, const GValue *value); @@ -198,30 +206,6 @@ register_basic (int typecode, const DBusGTypeMarshalData *typedata) set_type_metadata (basic_typecode_to_gtype (typecode), typedata); } -static void -register_array (int typecode, const DBusGTypeMarshalData *typedata) -{ - GType elt_gtype; - GType gtype; - - elt_gtype = basic_typecode_to_gtype (typecode); - gtype = dbus_g_type_get_collection ("GArray", elt_gtype); - set_type_metadata (gtype, typedata); -} - -static void -register_dict (int key_type, int value_type, const DBusGTypeMarshalData *typedata) -{ - GType key_gtype; - GType value_gtype; - GType gtype; - - key_gtype = basic_typecode_to_gtype (key_type); - value_gtype = basic_typecode_to_gtype (value_type); - gtype = dbus_g_type_get_map ("GHashTable", key_gtype, value_gtype); - set_type_metadata (gtype, typedata); -} - void dbus_g_value_types_init (void) { @@ -240,14 +224,6 @@ dbus_g_value_types_init (void) marshal_basic, demarshal_basic }; - static const DBusGTypeMarshalVtable garray_basic_vtable = { - marshal_garray_basic, - demarshal_garray_basic - }; - static const DBusGTypeMarshalVtable ghashtable_vtable = { - marshal_map, - demarshal_ghashtable - }; /* Register basic types */ { @@ -374,56 +350,8 @@ dbus_g_value_types_init (void) set_type_metadata (G_TYPE_STRV, &typedata); }; - { - static const DBusGTypeMarshalData typedata = { - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BOOLEAN_AS_STRING, - &garray_basic_vtable - }; - register_array (DBUS_TYPE_BOOLEAN, &typedata); - } - { - static const DBusGTypeMarshalData typedata = { - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, - &garray_basic_vtable - }; - register_array (DBUS_TYPE_BYTE, &typedata); - } - { - static const DBusGTypeMarshalData typedata = { - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_UINT32_AS_STRING, - &garray_basic_vtable - }; - register_array (DBUS_TYPE_UINT32, &typedata); - } - { - static const DBusGTypeMarshalData typedata = { - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING, - &garray_basic_vtable - }; - register_array (DBUS_TYPE_INT32, &typedata); - } - { - static const DBusGTypeMarshalData typedata = { - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_UINT64_AS_STRING, - &garray_basic_vtable - }; - register_array (DBUS_TYPE_UINT64, &typedata); - } - { - static const DBusGTypeMarshalData typedata = { - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT64_AS_STRING, - &garray_basic_vtable - }; - register_array (DBUS_TYPE_INT64, &typedata); - } - { - static const DBusGTypeMarshalData typedata = { - DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &ghashtable_vtable, - }; - register_dict (DBUS_TYPE_STRING, DBUS_TYPE_STRING, &typedata); - } + /* Register some types specific to the D-BUS GLib bindings */ { static const DBusGTypeMarshalVtable vtable = { marshal_proxy, @@ -535,6 +463,7 @@ dbus_g_value_iterator_get_values (DBusGValueIterator *iter, context.gconnection = (iterval->value.recurse.toplevel)->value.toplevel.connection; context.proxy = (iterval->value.recurse.toplevel)->value.toplevel.proxy; + if (!dbus_gvalue_demarshal (&context, &(iterval->value.recurse.iterator), value, @@ -661,6 +590,10 @@ dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client) DBusSignatureIter subiter; g_assert (dbus_type_is_container (current_type)); + + if (current_type == DBUS_TYPE_VARIANT) + return g_value_get_type (); + dbus_signature_iter_recurse (iter, &subiter); if (current_type == DBUS_TYPE_ARRAY) @@ -673,8 +606,6 @@ dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client) } else if (current_type == DBUS_TYPE_STRUCT) return signature_iter_to_g_type_struct (&subiter, is_client); - else if (current_type == DBUS_TYPE_VARIANT) - return g_value_get_type (); else if (current_type == DBUS_TYPE_DICT_ENTRY) return G_TYPE_INVALID; else @@ -721,10 +652,6 @@ dbus_gtype_to_signature (GType gtype) char *ret; DBusGTypeMarshalData *typedata; - typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ()); - if (typedata == NULL) - return NULL; - if (dbus_g_type_is_collection (gtype)) { GType elt_gtype; @@ -751,7 +678,12 @@ dbus_gtype_to_signature (GType gtype) g_free (val_subsig); } else - ret = g_strdup (typedata->sig); + { + typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ()); + if (typedata == NULL) + return NULL; + ret = g_strdup (typedata->sig); + } return ret; } @@ -1066,53 +998,18 @@ demarshal_strv (DBusGValueMarshalCtx *context, } static gboolean -demarshal_garray_basic (DBusGValueMarshalCtx *context, - DBusMessageIter *iter, - GValue *value, - GError **error) -{ - DBusMessageIter subiter; - GArray *ret; - GType elt_gtype; - int elt_size; - void *msgarray; - int msgarray_len; - - dbus_message_iter_recurse (iter, &subiter); - - elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value)); - g_assert (elt_gtype != G_TYPE_INVALID); - g_assert (dbus_g_type_is_fixed (elt_gtype)); - - elt_size = dbus_g_type_fixed_get_size (elt_gtype); - - ret = g_array_new (FALSE, TRUE, elt_size); - - msgarray = NULL; - dbus_message_iter_get_fixed_array (&subiter, - &msgarray, - &msgarray_len); - g_assert (msgarray != NULL); - g_assert (msgarray_len >= 0); - g_array_append_vals (ret, msgarray, (guint) msgarray_len); - - g_value_set_boxed_take_ownership (value, ret); - - return TRUE; -} - -static gboolean -demarshal_ghashtable (DBusGValueMarshalCtx *context, - DBusMessageIter *iter, - GValue *value, - GError **error) +demarshal_map (DBusGValueMarshalCtx *context, + DBusMessageIter *iter, + GValue *value, + GError **error) { GType gtype; DBusMessageIter subiter; int current_type; - GHashTable *ret; + gpointer ret; GType key_gtype; GType value_gtype; + DBusGTypeSpecializedAppendContext appendctx; current_type = dbus_message_iter_get_arg_type (iter); if (current_type != DBUS_TYPE_ARRAY) @@ -1140,14 +1037,12 @@ demarshal_ghashtable (DBusGValueMarshalCtx *context, } key_gtype = dbus_g_type_get_map_key_specialization (gtype); - g_assert (dbus_gtype_is_valid_hash_key (key_gtype)); value_gtype = dbus_g_type_get_map_value_specialization (gtype); - g_assert (dbus_gtype_is_valid_hash_value (value_gtype)); - ret = g_hash_table_new_full (dbus_g_hash_func_from_gtype (key_gtype), - dbus_g_hash_equal_from_gtype (key_gtype), - dbus_g_hash_free_from_gtype (key_gtype), - dbus_g_hash_free_from_gtype (value_gtype)); + ret = dbus_g_type_specialized_construct (gtype); + g_value_set_boxed_take_ownership (value, ret); + + dbus_g_type_specialized_init_append (value, &appendctx); while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID) { @@ -1176,14 +1071,11 @@ demarshal_ghashtable (DBusGValueMarshalCtx *context, error)) return FALSE; - dbus_g_hash_table_insert_steal_values (ret, - &key_value, - &value_value); - /* Ownership of values passes to hash table, don't unset */ + dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value); + /* Ownership of values passes to map, don't unset */ dbus_message_iter_next (&subiter); } - g_value_set_boxed_take_ownership (value, ret); return TRUE; } @@ -1200,6 +1092,8 @@ get_type_demarshaller (GType type) return demarshal_recurse; if (dbus_g_type_is_collection (type)) return demarshal_collection; + if (dbus_g_type_is_map (type)) + return demarshal_map; g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type)); return NULL; @@ -1216,6 +1110,24 @@ demarshal_collection (DBusGValueMarshalCtx *context, { GType coltype; GType subtype; + + coltype = G_VALUE_TYPE (value); + subtype = dbus_g_type_get_collection_specialization (coltype); + + if (dbus_g_type_is_fixed (subtype)) + return demarshal_collection_array (context, iter, value, error); + else + return demarshal_collection_ptrarray (context, iter, value, error); +} + +static gboolean +demarshal_collection_ptrarray (DBusGValueMarshalCtx *context, + DBusMessageIter *iter, + GValue *value, + GError **error) +{ + GType coltype; + GType subtype; gpointer instance; DBusGTypeSpecializedAppendContext ctx; DBusGValueDemarshalFunc demarshaller; @@ -1254,7 +1166,7 @@ demarshal_collection (DBusGValueMarshalCtx *context, instance = dbus_g_type_specialized_construct (coltype); g_value_set_boxed_take_ownership (value, instance); - dbus_g_type_specialized_collection_init_append (value, &ctx); + dbus_g_type_specialized_init_append (value, &ctx); while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID) { @@ -1277,6 +1189,42 @@ demarshal_collection (DBusGValueMarshalCtx *context, return TRUE; } +static gboolean +demarshal_collection_array (DBusGValueMarshalCtx *context, + DBusMessageIter *iter, + GValue *value, + GError **error) +{ + DBusMessageIter subiter; + GArray *ret; + GType elt_gtype; + int elt_size; + void *msgarray; + int msgarray_len; + + dbus_message_iter_recurse (iter, &subiter); + + elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value)); + g_assert (elt_gtype != G_TYPE_INVALID); + g_assert (dbus_g_type_is_fixed (elt_gtype)); + + elt_size = dbus_g_type_fixed_get_size (elt_gtype); + + ret = g_array_new (FALSE, TRUE, elt_size); + + msgarray = NULL; + dbus_message_iter_get_fixed_array (&subiter, + &msgarray, + &msgarray_len); + g_assert (msgarray != NULL); + g_assert (msgarray_len >= 0); + g_array_append_vals (ret, msgarray, (guint) msgarray_len); + + g_value_set_boxed_take_ownership (value, ret); + + return TRUE; +} + static gboolean demarshal_recurse (DBusGValueMarshalCtx *context, DBusMessageIter *iter, @@ -1544,50 +1492,6 @@ marshal_strv (DBusMessageIter *iter, return ret; } -static gboolean -marshal_garray_basic (DBusMessageIter *iter, - const GValue *value) -{ - GType elt_gtype; - DBusMessageIter subiter; - GArray *array; - guint elt_size; - char *subsignature_str; - - elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value)); - /* FIXME - this means we can't send an array of DBusGValue right now... */ - subsignature_str = dbus_gtype_to_signature (elt_gtype); - g_assert (subsignature_str != NULL); - - elt_size = dbus_g_type_fixed_get_size (elt_gtype); - - array = g_value_get_boxed (value); - - if (!dbus_message_iter_open_container (iter, - DBUS_TYPE_ARRAY, - subsignature_str, - &subiter)) - goto oom; - - /* TODO - This assumes that basic values are the same size - * is this always true? If it is we can probably avoid - * a lot of the overhead in _marshal_basic_instance... - */ - if (!dbus_message_iter_append_fixed_array (&subiter, - subsignature_str[0], - &(array->data), - array->len)) - goto oom; - - if (!dbus_message_iter_close_container (iter, &subiter)) - goto oom; - g_free (subsignature_str); - return TRUE; - oom: - g_error ("out of memory"); - return FALSE; -} - static gboolean marshal_proxy (DBusMessageIter *iter, const GValue *value) @@ -1791,6 +1695,8 @@ get_type_marshaller (GType type) return marshal_recurse; if (dbus_g_type_is_collection (type)) return marshal_collection; + if (dbus_g_type_is_map (type)) + return marshal_map; g_warning ("No marshaller registered for type \"%s\"", g_type_name (type)); return NULL; @@ -1822,6 +1728,22 @@ collection_marshal_iterator (const GValue *eltval, static gboolean marshal_collection (DBusMessageIter *iter, const GValue *value) +{ + GType coltype; + GType subtype; + + coltype = G_VALUE_TYPE (value); + subtype = dbus_g_type_get_collection_specialization (coltype); + + if (dbus_g_type_is_fixed (subtype)) + return marshal_collection_array (iter, value); + else + return marshal_collection_ptrarray (iter, value); +} + +static gboolean +marshal_collection_ptrarray (DBusMessageIter *iter, + const GValue *value) { GType coltype; GType elt_gtype; @@ -1861,6 +1783,51 @@ marshal_collection (DBusMessageIter *iter, return FALSE; } + +static gboolean +marshal_collection_array (DBusMessageIter *iter, + const GValue *value) +{ + GType elt_gtype; + DBusMessageIter subiter; + GArray *array; + guint elt_size; + char *subsignature_str; + + elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value)); + g_assert (dbus_g_type_is_fixed (elt_gtype)); + subsignature_str = dbus_gtype_to_signature (elt_gtype); + g_assert (subsignature_str != NULL); + + elt_size = dbus_g_type_fixed_get_size (elt_gtype); + + array = g_value_get_boxed (value); + + if (!dbus_message_iter_open_container (iter, + DBUS_TYPE_ARRAY, + subsignature_str, + &subiter)) + goto oom; + + /* TODO - This assumes that basic values are the same size + * is this always true? If it is we can probably avoid + * a lot of the overhead in _marshal_basic_instance... + */ + if (!dbus_message_iter_append_fixed_array (&subiter, + subsignature_str[0], + &(array->data), + array->len)) + goto oom; + + if (!dbus_message_iter_close_container (iter, &subiter)) + goto oom; + g_free (subsignature_str); + return TRUE; + oom: + g_error ("out of memory"); + return FALSE; +} + static gboolean marshal_recurse (DBusMessageIter *iter, const GValue *value) @@ -1882,3 +1849,54 @@ dbus_gvalue_marshal (DBusMessageIter *iter, return FALSE; return marshaller (iter, value); } + +#ifdef DBUS_BUILD_TESTS + +static void +assert_type_maps_to (GType gtype, const char *expected_sig) +{ + char *sig; + sig = dbus_gtype_to_signature (gtype); + g_assert (sig != NULL); + g_assert (!strcmp (expected_sig, sig)); + g_free (sig); +} + +static void +assert_signature_maps_to (const char *sig, GType expected_gtype) +{ + g_assert (dbus_gtype_from_signature (sig, TRUE) == expected_gtype); +} + +static void +assert_bidirectional_mapping (GType gtype, const char *expected_sig) +{ + assert_type_maps_to (gtype, expected_sig); + assert_signature_maps_to (expected_sig, gtype); +} + +/** + * @ingroup DBusGLibInternals + * Unit test for general glib stuff + * @returns #TRUE on success. + */ +gboolean +_dbus_gvalue_test (const char *test_data_dir) +{ + dbus_g_value_types_init (); + + assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING); + assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING); + assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING); + + assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING); + assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING); + assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT), + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING); + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/glib/examples/statemachine/statemachine-client.c b/glib/examples/statemachine/statemachine-client.c index 54c630ff..88b21847 100644 --- a/glib/examples/statemachine/statemachine-client.c +++ b/glib/examples/statemachine/statemachine-client.c @@ -59,8 +59,9 @@ typedef struct { char *name; char *state; + gdouble progress; DBusGProxy *proxy; - DBusGProxyCall *get_initial_state_call; + DBusGProxyCall *get_progress_call; } MachineInfo; typedef struct @@ -90,6 +91,15 @@ proxy_to_iter (GtkTreeModel *model, DBusGProxy *proxy, GtkTreeIter *iter) return FALSE; } +static void +signal_row_change (ClientState *state, GtkTreeIter *iter) +{ + GtkTreePath *path; + path = gtk_tree_model_get_path (state->store, iter); + gtk_tree_model_row_changed (state->store, path, iter); + gtk_tree_path_free (path); +} + static void get_machine_info_cb (DBusGProxy *proxy, DBusGProxyCall *call, @@ -115,13 +125,67 @@ get_machine_info_cb (DBusGProxy *proxy, info->name = name; g_free (info->state); info->state = statename; - { - GtkTreePath *path; - path = gtk_tree_model_get_path (state->store, &iter); - gtk_tree_model_row_changed (state->store, path, &iter); - gtk_tree_path_free (path); - } - info->get_initial_state_call = NULL; + signal_row_change (state, &iter); +} + +static void +set_proxy_acquisition_progress (ClientState *state, + DBusGProxy *proxy, + double progress) +{ + MachineInfo *info; + GtkTreeIter iter; + + if (!proxy_to_iter (state->store, proxy, &iter)) + g_assert_not_reached (); + gtk_tree_model_get (state->store, &iter, 0, &info, -1); + + /* Ignore machines in unknown state */ + if (!info->state) + return; + + if (strcmp (info->state, "Acquired")) + lose ("Got AcquisitionProgress signal in bad state %s", + info->state); + + g_print ("Got acquisition progress change for %p (%s) to %f\n", proxy, info->name ? info->name : "(unknown)", progress); + + info->progress = progress; + + signal_row_change (state, &iter); +} + +static void +proxy_acquisition_changed_cb (DBusGProxy *proxy, + double progress, + gpointer user_data) +{ + set_proxy_acquisition_progress (user_data, proxy, progress); +} + +static void +get_acquiring_progress_cb (DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + GError *error = NULL; + MachineInfo *info; + GtkTreeIter iter; + ClientState *state = user_data; + gdouble progress; + + if (!proxy_to_iter (state->store, proxy, &iter)) + g_assert_not_reached (); + gtk_tree_model_get (state->store, &iter, 0, &info, -1); + + g_assert (info->get_progress_call == call); + + if (!dbus_g_proxy_end_call (proxy, call, &error, + G_TYPE_DOUBLE, &progress, G_TYPE_INVALID)) + lose_gerror ("Failed to complete GetAcquiringProgress call", error); + info->get_progress_call = NULL; + + set_proxy_acquisition_progress (state, proxy, progress); } static void @@ -139,25 +203,27 @@ proxy_state_changed_cb (DBusGProxy *proxy, g_print ("Got state change for %p (%s) to %s\n", proxy, info->name ? info->name : "(unknown)", statename); - /* If we got a signal for the state, we shouldn't update - * based on the (possibly stale) call - */ - if (info->get_initial_state_call != NULL) - { - g_print ("Cancelling outstanding GetInfo call for %p due to signal\n", proxy); - dbus_g_proxy_cancel_call (proxy, info->get_initial_state_call); - info->get_initial_state_call = NULL; - } - g_free (info->state); info->state = g_strdup (statename); - { - GtkTreePath *path; - path = gtk_tree_model_get_path (state->store, &iter); - gtk_tree_model_row_changed (state->store, path, &iter); - gtk_tree_path_free (path); - } + if (!strcmp (info->state, "Acquired")) + { + g_print ("Starting GetAcquiringProgress call for %p\n", info->proxy); + if (info->get_progress_call != NULL) + { + dbus_g_proxy_cancel_call (info->proxy, info->get_progress_call); + info->get_progress_call = NULL; + } + info->get_progress_call = + dbus_g_proxy_begin_call (info->proxy, "GetAcquiringProgress", + get_acquiring_progress_cb, + state, NULL, + G_TYPE_INVALID); + } + else + info->progress = 0.0; + + signal_row_change (state, &iter); } static void @@ -172,6 +238,7 @@ add_machine (ClientState *state, info = g_new0 (MachineInfo, 1); info->name = g_strdup (name); info->state = g_strdup (mstate); + info->progress = 0.0; info->proxy = dbus_g_proxy_new_for_name (state->bus, "com.example.StateServer", @@ -181,14 +248,11 @@ add_machine (ClientState *state, if (!info->state) { g_print ("Starting GetInfo call for %p\n", info->proxy); - info->get_initial_state_call - = dbus_g_proxy_begin_call (info->proxy, "GetInfo", - get_machine_info_cb, - state, NULL, - G_TYPE_INVALID); + dbus_g_proxy_begin_call (info->proxy, "GetInfo", + get_machine_info_cb, + state, NULL, + G_TYPE_INVALID); } - else - info->get_initial_state_call = NULL; /* Watch for state changes */ dbus_g_proxy_add_signal (info->proxy, "StateChanged", @@ -200,6 +264,15 @@ add_machine (ClientState *state, state, NULL); + dbus_g_proxy_add_signal (info->proxy, "AcquisitionProgress", + G_TYPE_DOUBLE, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal (info->proxy, + "AcquisitionProgress", + G_CALLBACK (proxy_acquisition_changed_cb), + state, + NULL); + gtk_list_store_prepend (GTK_LIST_STORE (state->store), &iter); gtk_list_store_set (GTK_LIST_STORE (state->store), &iter, 0, info, -1); @@ -306,6 +379,12 @@ do_a_state_change (ClientState *state) g_print ("Sending Start request to machine %s\n", info->name); dbus_g_proxy_call_no_reply (info->proxy, "Start", G_TYPE_INVALID); } + else if (!strcmp (info->state, "Loading")) + { + + g_print ("Sending Reacquire request to machine %s\n", info->name); + dbus_g_proxy_call_no_reply (info->proxy, "Reacquire", G_TYPE_INVALID); + } else { g_print ("Sending Shutdown request to machine %s\n", info->name); @@ -318,7 +397,7 @@ do_something_random_2 (gpointer data) { ClientState *state = data; do_a_state_change (state); - g_timeout_add (g_random_int_range (500, 3000), do_something_random_2, state); + g_timeout_add (g_random_int_range (2000, 5000), do_something_random_2, state); return FALSE; } @@ -328,12 +407,13 @@ do_something_random (gpointer data) ClientState *state = data; gint n_children; - switch (g_random_int_range (0, 2)) + switch (g_random_int_range (0, 3)) { case 0: send_create_machine (state); break; case 1: + case 2: do_a_state_change (state); break; default: @@ -341,8 +421,11 @@ do_something_random (gpointer data) } n_children = gtk_tree_model_iter_n_children (state->store, NULL); - if (n_children >= 8) - g_timeout_add (g_random_int_range (500, 3000), do_something_random_2, state); + if (n_children >= 5) + { + g_print ("MAX children reached, switching to state changes only\n"); + g_timeout_add (g_random_int_range (500, 3000), do_something_random_2, state); + } else g_timeout_add (g_random_int_range (500, 3000), do_something_random, state); return FALSE; @@ -406,6 +489,34 @@ sort_by_state (GtkTreeModel *model, info_b ? info_b->state : ""); } +static void +set_cell_progress (GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer data) +{ + MachineInfo *info; + + gtk_tree_model_get (tree_model, iter, 0, &info, -1); + + g_object_set (cell, "value", (int) (info->progress * 100), NULL); +} + +static gint +sort_by_progress (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) +{ + MachineInfo *info_a, *info_b; + + gtk_tree_model_get (model, a, 0, &info_a, -1); + gtk_tree_model_get (model, b, 0, &info_b, -1); + + return info_a->progress > info_b->progress ? 1 : -1; +} + static void get_machines_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer data) { @@ -458,6 +569,17 @@ get_machines_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer data) 0, sort_by_state, NULL, NULL); gtk_tree_view_column_set_sort_column_id (col, 0); gtk_tree_view_append_column (GTK_TREE_VIEW (state->view), col); + + rend = gtk_cell_renderer_progress_new (); + col = gtk_tree_view_column_new_with_attributes (_("Progress"), + rend, + NULL); + gtk_tree_view_column_set_cell_data_func (col, rend, set_cell_progress, NULL, NULL); + gtk_tree_view_column_set_resizable (col, TRUE); + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (state->store), + 0, sort_by_progress, NULL, NULL); + gtk_tree_view_column_set_sort_column_id (col, 0); + gtk_tree_view_append_column (GTK_TREE_VIEW (state->view), col); for (i = 0; i < objs->len; i++) { diff --git a/glib/examples/statemachine/statemachine-server.c b/glib/examples/statemachine/statemachine-server.c index 7cadf1fe..2cbf39fe 100644 --- a/glib/examples/statemachine/statemachine-server.c +++ b/glib/examples/statemachine/statemachine-server.c @@ -104,6 +104,26 @@ sm_server_get_property (GObject *object, } } +static void +machine_state_changed_cb (SMObject *obj, const char *state, gpointer data) +{ + char *name; + + g_object_get (obj, "name", &name, NULL); + g_print ("Machine %s switching to state %s\n", name, state); + g_free (name); +} + +static void +machine_acquisition_changed_cb (SMObject *obj, gdouble progress, gpointer data) +{ + char *name; + + g_object_get (obj, "name", &name, NULL); + g_print ("Machine %s got progress %f\n", name, progress); + g_free (name); +} + gboolean sm_server_create_machine (SMServer *server, const char *name, GError **error) { @@ -130,6 +150,13 @@ sm_server_create_machine (SMServer *server, const char *name, GError **error) g_print ("Created state machine with name %s at %s\n", name, path); + g_signal_connect_object (machine, "state-changed", + G_CALLBACK (machine_state_changed_cb), + NULL, 0); + g_signal_connect_object (machine, "acquisition-progress", + G_CALLBACK (machine_acquisition_changed_cb), + NULL, 0); + g_signal_emit (server, sm_server_signals[MACHINE_CREATED], 0, name, path); return TRUE; diff --git a/glib/examples/statemachine/statemachine.c b/glib/examples/statemachine/statemachine.c index 2bde0058..c94e2945 100644 --- a/glib/examples/statemachine/statemachine.c +++ b/glib/examples/statemachine/statemachine.c @@ -103,8 +103,8 @@ sm_object_state_get_type (void) ENUM_ENTRY (SM_OBJECT_STATE_SHUTDOWN, "Shutdown"), ENUM_ENTRY (SM_OBJECT_STATE_INITIALIZED, "Loading"), - ENUM_ENTRY (SM_OBJECT_STATE_ACQUIRED, "Resource acquired"), - ENUM_ENTRY (SM_OBJECT_STATE_OPERATING, "Operating normally"), + ENUM_ENTRY (SM_OBJECT_STATE_ACQUIRED, "Acquired"), + ENUM_ENTRY (SM_OBJECT_STATE_OPERATING, "Operating"), { 0, 0, 0 } }; @@ -175,6 +175,21 @@ sm_object_get_property (GObject *object, } } +static const char * +state_to_string (SMObjectState state) +{ + GEnumValue *value; + GEnumClass *prop_class; + const char *ret; + + prop_class = g_type_class_ref (SM_TYPE_OBJECT_STATE); + value = g_enum_get_value (prop_class, state); + ret = value->value_nick; + + g_type_class_unref (prop_class); + return ret; +} + static void queue_task (SMObject *object, guint delay, GSourceFunc func) { @@ -188,6 +203,8 @@ idle_state_change (gpointer data) { SMObject *object = data; + g_print ("doing idle state change for %s to %s\n", + object->name, state_to_string (object->requested_state)); state_change (object, object->requested_state); return FALSE; } @@ -197,7 +214,8 @@ idle_further_acquire (gpointer data) { SMObject *object = data; - object->acquisition_progress += g_random_double_range (0.05, 0.5); + g_print ("doing idle acquisition for machine %s\n", object->name); + object->acquisition_progress += g_random_double_range (0.20, 0.7); if (object->acquisition_progress > 1.0) { object->acquisition_progress = 1.0; @@ -220,26 +238,10 @@ clear_pending_tasks (SMObject *object) object->pending_tasks = NULL; } -static const char * -state_to_string (SMObjectState state) -{ - GEnumValue *value; - GEnumClass *prop_class; - const char *ret; - - prop_class = g_type_class_ref (SM_TYPE_OBJECT_STATE); - value = g_enum_get_value (prop_class, state); - ret = value->value_nick; - - g_type_class_unref (prop_class); - return ret; -} - static void state_change (SMObject *object, SMObjectState new_state) { g_signal_emit (object, sm_object_signals[STATE_CHANGED], 0, - state_to_string (object->state), state_to_string (new_state)); clear_pending_tasks (object); @@ -288,7 +290,7 @@ sm_object_start (SMObject *object, GError **error) gboolean sm_object_shutdown (SMObject *object, GError **error) { - if (object->state != SM_OBJECT_STATE_INITIALIZED) + if (object->state == SM_OBJECT_STATE_SHUTDOWN) { g_set_error (error, SM_ERROR, @@ -321,7 +323,7 @@ sm_object_reinitialize (SMObject *object, GError **error) gboolean sm_object_reacquire (SMObject *object, GError **error) { - if (object->state != SM_OBJECT_STATE_ACQUIRED) + if (object->state == SM_OBJECT_STATE_ACQUIRED) { g_set_error (error, SM_ERROR, diff --git a/test/glib/test-dbus-glib.c b/test/glib/test-dbus-glib.c index 15cd769a..4fbe797e 100644 --- a/test/glib/test-dbus-glib.c +++ b/test/glib/test-dbus-glib.c @@ -26,6 +26,13 @@ static gboolean proxy_destroy_and_nameowner_complete = FALSE; static void lose (const char *fmt, ...) G_GNUC_NORETURN G_GNUC_PRINTF (1, 2); static void lose_gerror (const char *prefix, GError *error) G_GNUC_NORETURN; +static void +unset_and_free_gvalue (gpointer val) +{ + g_value_unset (val); + g_free (val); +} + static gboolean timed_exit (gpointer loop) { @@ -40,6 +47,7 @@ proxy_destroyed_cb (DBusGProxy *proxy, gpointer user_data) proxy_destroyed = TRUE; if (proxy_destroy_and_nameowner && !proxy_destroy_and_nameowner_complete && await_terminating_service == NULL) { + g_source_remove (exit_timeout); g_main_loop_quit (loop); proxy_destroy_and_nameowner_complete = TRUE; } @@ -62,11 +70,13 @@ name_owner_changed (DBusGProxy *proxy, await_terminating_service = NULL; if (proxy_destroy_and_nameowner && !proxy_destroy_and_nameowner_complete && proxy_destroyed) { + g_source_remove (exit_timeout); g_main_loop_quit (loop); proxy_destroy_and_nameowner_complete = TRUE; } else if (!proxy_destroy_and_nameowner) { + g_source_remove (exit_timeout); g_main_loop_quit (loop); } } @@ -837,6 +847,50 @@ main (int argc, char **argv) run_mainloop (); + { + GValue *val; + GHashTable *table; + GHashTable *ret_table; + + table = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, unset_and_free_gvalue); + + val = g_new0 (GValue, 1); + g_value_init (val, G_TYPE_UINT); + g_value_set_uint (val, 42); + g_hash_table_insert (table, g_strdup ("foo"), val); + + val = g_new0 (GValue, 1); + g_value_init (val, G_TYPE_STRING); + g_value_set_string (val, "hello"); + g_hash_table_insert (table, g_strdup ("bar"), val); + + ret_table = NULL; + g_print ("Calling ManyStringify\n"); + if (!dbus_g_proxy_call (proxy, "ManyStringify", &error, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), table, + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &ret_table, + G_TYPE_INVALID)) + lose_gerror ("Failed to complete ManyStringify call", error); + + g_assert (ret_table != NULL); + g_assert (g_hash_table_size (ret_table) == 2); + + val = g_hash_table_lookup (ret_table, "foo"); + g_assert (val != NULL); + g_assert (G_VALUE_HOLDS_STRING (val)); + g_assert (!strcmp ("42", g_value_get_string (val))); + + val = g_hash_table_lookup (ret_table, "bar"); + g_assert (val != NULL); + g_assert (G_VALUE_HOLDS_STRING (val)); + g_assert (!strcmp ("hello", g_value_get_string (val))); + + g_hash_table_destroy (table); + g_hash_table_destroy (ret_table); + } + { guint val; char *ret_path; @@ -1135,6 +1189,9 @@ main (int argc, char **argv) lose_gerror ("Failed to complete Uppercase call", error); g_free (v_STRING_2); + if (getenv ("DBUS_GLIB_TEST_SLEEP_AFTER_ACTIVATION1")) + g_usleep (8 * G_USEC_PER_SEC); + dbus_g_proxy_add_signal (proxy, "Frobnicate", G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_connect_signal (proxy, "Frobnicate", @@ -1175,6 +1232,9 @@ main (int argc, char **argv) G_TYPE_INVALID, G_TYPE_INVALID)) lose_gerror ("Failed to complete EmitFrobnicate call", error); + if (getenv ("DBUS_GLIB_TEST_SLEEP_AFTER_ACTIVATION2")) + g_usleep (8 * G_USEC_PER_SEC); + dbus_g_connection_flush (connection); exit_timeout = g_timeout_add (5000, timed_exit, loop); g_main_loop_run (loop); diff --git a/test/glib/test-service-glib.c b/test/glib/test-service-glib.c index a9e57926..580eb107 100644 --- a/test/glib/test-service-glib.c +++ b/test/glib/test-service-glib.c @@ -63,6 +63,8 @@ gboolean my_object_many_return (MyObject *obj, guint32 *arg0, char **arg1, gint3 gboolean my_object_recursive1 (MyObject *obj, GArray *array, guint32 *len_ret, GError **error); gboolean my_object_recursive2 (MyObject *obj, guint32 reqlen, GArray **array, GError **error); +gboolean my_object_many_stringify (MyObject *obj, GHashTable *vals, GHashTable **ret, GError **error); + gboolean my_object_objpath (MyObject *obj, const char *in, char **arg1, GError **error); gboolean my_object_get_objs (MyObject *obj, GPtrArray **objs, GError **error); @@ -397,6 +399,38 @@ my_object_many_uppercase (MyObject *obj, const char * const *in, char ***out, GE return TRUE; } +static void +hash_foreach_stringify (gpointer key, gpointer val, gpointer user_data) +{ + const char *keystr = key; + const GValue *value = val; + GValue *sval; + GHashTable *ret = user_data; + + sval = g_new0 (GValue, 1); + g_value_init (sval, G_TYPE_STRING); + if (!g_value_transform (value, sval)) + g_assert_not_reached (); + + g_hash_table_insert (ret, g_strdup (keystr), sval); +} + +static void +unset_and_free_gvalue (gpointer val) +{ + g_value_unset (val); + g_free (val); +} + +gboolean +my_object_many_stringify (MyObject *obj, GHashTable /* char * -> GValue * */ *vals, GHashTable /* char * -> GValue * */ **ret, GError **error) +{ + *ret = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, unset_and_free_gvalue); + g_hash_table_foreach (vals, hash_foreach_stringify, *ret); + return TRUE; +} + gboolean my_object_objpath (MyObject *obj, const char *incoming, char **outgoing, GError **error) { diff --git a/test/glib/test-service-glib.xml b/test/glib/test-service-glib.xml index 272f7b23..c299a80c 100644 --- a/test/glib/test-service-glib.xml +++ b/test/glib/test-service-glib.xml @@ -95,6 +95,11 @@ + + + + + -- cgit