From 03d040311afd4b988b9a277a8aa360fa20243c92 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 30 Jun 2005 18:22:10 +0000 Subject: 2005-06-30 Colin Walters * test/glib/test-dbus-glib.c: * test/glib/test-service-glib.c: * test/glib/test-service-glib.xml: Update tests for new error setting bits, also add async tests (patch from Ross Burton). * test/glib/Makefile.am (test_service_glib_LDADD): Add DBUS_GLIB_THREADS_LIBS. * glib/dbus-gproxy.c (get_name_owner) (dbus_g_pending_call_end_valist): Ditto. * glib/dbus-gobject.c (error_metadata): New mapping from GError domain (GQuark) to DBusGErrorInfo. (gerror_domaincode_to_dbus_error_name): Attempt to look up error quark in error_metadata. Take message interface as default error message interface. (gerror_to_dbus_error_message): Pass message interface. (dbus_set_g_error): Resurrected. (dbus_g_error_info_free): New function. (dbus_g_object_type_install_info): Use g_type_class_ref instead of _peek to actually create the object class if it hasn't been created yet. (dbus_g_error_domain_register): New function. * glib/dbus-gmain.c (dbus_g_bus_get): Switch to dbus_set_g_error. * glib/dbus-gparser.c (validate_signature): Ditto. * dbus/dbus-glib.h (dbus_g_error_set): Delete. (dbus_g_error_domain_register): Prototype. * glib/dbus-glib.c (dbus_g_error_set): Delete. Update tests. --- ChangeLog | 36 ++++++++++++ dbus/dbus-glib.h | 7 ++- glib/dbus-glib.c | 45 +------------- glib/dbus-gmain.c | 3 +- glib/dbus-gobject.c | 127 +++++++++++++++++++++++++++++++++++++++- glib/dbus-gparser.c | 3 +- glib/dbus-gproxy.c | 6 +- test/glib/Makefile.am | 2 +- test/glib/test-dbus-glib.c | 16 ++++- test/glib/test-service-glib.c | 99 +++++++++++++++++++++++++++++-- test/glib/test-service-glib.xml | 10 ++++ 11 files changed, 293 insertions(+), 61 deletions(-) diff --git a/ChangeLog b/ChangeLog index bce59c68..0476f339 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +2005-06-30 Colin Walters + + * test/glib/test-dbus-glib.c: + * test/glib/test-service-glib.c: + * test/glib/test-service-glib.xml: Update tests for new error + setting bits, also add async tests (patch from Ross Burton). + + * test/glib/Makefile.am (test_service_glib_LDADD): Add + DBUS_GLIB_THREADS_LIBS. + + * glib/dbus-gproxy.c (get_name_owner) + (dbus_g_pending_call_end_valist): Ditto. + + * glib/dbus-gobject.c (error_metadata): New mapping from GError + domain (GQuark) to DBusGErrorInfo. + (gerror_domaincode_to_dbus_error_name): Attempt to look up error + quark in error_metadata. Take message interface as default + error message interface. + (gerror_to_dbus_error_message): Pass message interface. + (dbus_set_g_error): Resurrected. + (dbus_g_error_info_free): New function. + (dbus_g_object_type_install_info): Use g_type_class_ref instead + of _peek to actually create the object class if it hasn't been + created yet. + (dbus_g_error_domain_register): New function. + + * glib/dbus-gmain.c (dbus_g_bus_get): Switch to dbus_set_g_error. + + * glib/dbus-gparser.c (validate_signature): Ditto. + + * dbus/dbus-glib.h (dbus_g_error_set): Delete. + (dbus_g_error_domain_register): Prototype. + + * glib/dbus-glib.c (dbus_g_error_set): Delete. + Update tests. + 2005-06-29 Colin Walters * dbus/dbus-glib.h: Delete DBUS_TYPE_G_PROXY_ARRAY. Add diff --git a/dbus/dbus-glib.h b/dbus/dbus-glib.h index 5e791e01..41b3d9c1 100644 --- a/dbus/dbus-glib.h +++ b/dbus/dbus-glib.h @@ -81,9 +81,6 @@ typedef enum #include } DBusGError; -void dbus_g_error_set (GError **error, - const char *name, - const char *msg); gboolean dbus_g_error_has_name (GError *error, const char *name); const char * dbus_g_error_get_name (GError *error); @@ -126,6 +123,10 @@ struct _DBusGObjectInfo void dbus_g_object_type_install_info (GType object_type, const DBusGObjectInfo *info); +void dbus_g_error_domain_register (GQuark domain, + const char * default_iface, + GType code_enum); + void dbus_g_connection_register_g_object (DBusGConnection *connection, const char *at_path, GObject *object); diff --git a/glib/dbus-glib.c b/glib/dbus-glib.c index 3153deef..5b30ce7a 100644 --- a/glib/dbus-glib.c +++ b/glib/dbus-glib.c @@ -26,6 +26,7 @@ #include #include "dbus-gtest.h" #include "dbus-gutils.h" +#include "dbus-gobject.h" #include #include @@ -149,41 +150,6 @@ dbus_g_error_quark (void) return quark; } -#include "dbus-glib-error-switch.h" - -/** - * Set a GError return location from a D-BUS error name and message. - * This function should only be used in the implementation of service - * methods. - * - * @param gerror location to store a GError, or #NULL - * @param name the D-BUS error name - * @param msg the D-BUS error detailed message - */ -void -dbus_g_error_set (GError **gerror, - const char *name, - const char *msg) -{ - int code; - g_return_if_fail (name != NULL); - g_return_if_fail (msg != NULL); - - code = dbus_error_to_gerror_code (name); - if (code == DBUS_GERROR_REMOTE_EXCEPTION) - g_set_error (gerror, DBUS_GERROR, - code, - "%s%c%s", - msg, - '\0', - name); - else - g_set_error (gerror, DBUS_GERROR, - code, - "%s", - msg); -} - /** * Determine whether D-BUS error name for a remote exception matches * the given name. This function is intended to be invoked on a @@ -463,7 +429,7 @@ _dbus_glib_test (const char *test_data_dir) dbus_error_init (&err); dbus_set_error_const (&err, DBUS_ERROR_NO_MEMORY, "Out of memory!"); - dbus_g_error_set (&gerror, err.name, err.message); + dbus_set_g_error (&gerror, &err); g_assert (gerror != NULL); g_assert (gerror->domain == DBUS_GERROR); g_assert (gerror->code == DBUS_GERROR_NO_MEMORY); @@ -472,13 +438,6 @@ _dbus_glib_test (const char *test_data_dir) dbus_error_init (&err); g_clear_error (&gerror); - dbus_g_error_set (&gerror, "com.example.Foo.BlahFailed", "blah failed"); - g_assert (gerror != NULL); - g_assert (gerror->domain == DBUS_GERROR); - g_assert (gerror->code == DBUS_GERROR_REMOTE_EXCEPTION); - g_assert (dbus_g_error_has_name (gerror, "com.example.Foo.BlahFailed")); - g_assert (!strcmp (gerror->message, "blah failed")); - return TRUE; } diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 6d3b56c8..9d45ca0e 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -28,6 +28,7 @@ #include "dbus-gtest.h" #include "dbus-gutils.h" #include "dbus-gvalue.h" +#include "dbus-gobject.h" #include "dbus-gvalue-utils.h" #include @@ -720,7 +721,7 @@ dbus_g_bus_get (DBusBusType type, connection = dbus_bus_get (type, &derror); if (connection == NULL) { - dbus_g_error_set (error, derror.name, derror.message); + dbus_set_g_error (error, &derror); dbus_error_free (&derror); return NULL; } diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c index 8e399796..c91f1851 100644 --- a/glib/dbus-gobject.c +++ b/glib/dbus-gobject.c @@ -39,9 +39,16 @@ * @{ */ +typedef struct +{ + char *default_iface; + GType code_enum; +} DBusGErrorInfo; + static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT; static GHashTable *info_hash = NULL; static GHashTable *marshal_table = NULL; +static GData *error_metadata = NULL; static char* uscore_to_wincaps (const char *uscore) @@ -696,6 +703,7 @@ lookup_object_and_method (GObject *object, static char * gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info, + const char *msg_interface, GQuark domain, gint code) { const char *domain_str; @@ -705,6 +713,36 @@ gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info, domain_str = object_error_domain_prefix_from_object_info (object_info); code_str = object_error_code_from_object_info (object_info, domain, code); + if (!domain_str || !code_str) + { + DBusGErrorInfo *info; + + g_static_rw_lock_reader_lock (&globals_lock); + + if (error_metadata != NULL) + info = g_datalist_id_get_data (&error_metadata, domain); + else + info = NULL; + + g_static_rw_lock_reader_unlock (&globals_lock); + + if (info) + { + GEnumValue *value; + GEnumClass *klass; + + klass = g_type_class_ref (info->code_enum); + value = g_enum_get_value (klass, code); + g_type_class_unref (klass); + + domain_str = info->default_iface; + code_str = value->value_nick; + } + } + + if (!domain_str) + domain_str = msg_interface; + if (!domain_str || !code_str) { /* If we can't map it sensibly, make up an error name */ @@ -752,7 +790,9 @@ gerror_to_dbus_error_message (const DBusGObjectInfo *object_info, else { char *error_name; - error_name = gerror_domaincode_to_dbus_error_name (object_info, error->domain, error->code); + error_name = gerror_domaincode_to_dbus_error_name (object_info, + dbus_message_get_interface (message), + error->domain, error->code); reply = dbus_message_new_error (message, error_name, error->message); g_free (error_name); } @@ -1256,6 +1296,40 @@ export_signals (DBusGConnection *connection, const DBusGObjectInfo *info, GObjec } } +#include "dbus-glib-error-switch.h" + +void +dbus_set_g_error (GError **gerror, + DBusError *error) +{ + int code; + + code = dbus_error_to_gerror_code (error->name); + if (code != DBUS_GERROR_REMOTE_EXCEPTION) + g_set_error (gerror, DBUS_GERROR, + code, + "%s", + error->message); + else + g_set_error (gerror, DBUS_GERROR, + code, + "%s%c%s", + error->message, + '\0', + error->name); +} + +static void +dbus_g_error_info_free (gpointer p) +{ + DBusGErrorInfo *info; + + info = p; + + g_free (info->default_iface); + g_free (info); +} + /** @} */ /* end of internals */ /** @@ -1287,7 +1361,7 @@ dbus_g_object_type_install_info (GType object_type, dbus_g_value_types_init (); - object_class = g_type_class_peek (object_type); + object_class = g_type_class_ref (object_type); g_return_if_fail (G_IS_OBJECT_CLASS (object_class)); @@ -1301,6 +1375,55 @@ dbus_g_object_type_install_info (GType object_type, g_hash_table_replace (info_hash, object_class, (void*) info); g_static_rw_lock_writer_unlock (&globals_lock); + + g_type_class_unref (object_class); +} + +/** + * Register a GError domain and set of codes with D-BUS. You must + * have created a GEnum for the error codes. This function will not + * be needed with an introspection-capable GLib. + * + * @param domain the GError domain + * @param default_iface the D-BUS interface used for error values by default, or #NULL + * @param code_enum a GType for a GEnum of the error codes + */ +void +dbus_g_error_domain_register (GQuark domain, + const char *default_iface, + GType code_enum) +{ + DBusGErrorInfo *info; + + g_return_if_fail (g_quark_to_string (domain) != NULL); + g_return_if_fail (code_enum != G_TYPE_INVALID); + g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM); + + g_static_rw_lock_writer_lock (&globals_lock); + + if (error_metadata == NULL) + g_datalist_init (&error_metadata); + + info = g_datalist_id_get_data (&error_metadata, domain); + + if (info != NULL) + { + g_warning ("Metadata for error domain \"%s\" already registered\n", + g_quark_to_string (domain)); + } + else + { + info = g_new0 (DBusGErrorInfo, 1); + info->default_iface = g_strdup (default_iface); + info->code_enum = code_enum; + + g_datalist_id_set_data_full (&error_metadata, + domain, + info, + dbus_g_error_info_free); + } + + g_static_rw_lock_writer_unlock (&globals_lock); } static void diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c index 90798b19..daf9bc8e 100644 --- a/glib/dbus-gparser.c +++ b/glib/dbus-gparser.c @@ -23,6 +23,7 @@ #include "dbus-gparser.h" #include "dbus/dbus-glib-lowlevel.h" #include "dbus-gidl.h" +#include "dbus-gobject.h" #include "dbus/dbus-signature.h" #include @@ -474,7 +475,7 @@ validate_signature (const char *str, if (!dbus_signature_validate (str, &derror)) { - dbus_g_error_set (error, derror.name, derror.message); + dbus_set_g_error (&derror, error); return FALSE; } return TRUE; diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 9ea4c16c..91cda82f 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -818,7 +818,7 @@ get_name_owner (DBusConnection *connection, error: g_assert (dbus_error_is_set (&derror)); - dbus_g_error_set (error, derror.name, derror.message); + dbus_set_g_error (error, &derror); dbus_error_free (&derror); out: @@ -2009,14 +2009,14 @@ dbus_g_pending_call_end_valist (DBusGConnection *connection, break; case DBUS_MESSAGE_TYPE_ERROR: dbus_set_error_from_message (&derror, reply); - dbus_g_error_set (error, derror.name, derror.message); + dbus_set_g_error (error, &derror); dbus_error_free (&derror); goto out; break; default: dbus_set_error (&derror, DBUS_ERROR_FAILED, "Reply was neither a method return nor an exception"); - dbus_g_error_set (error, derror.name, derror.message); + dbus_set_g_error (error, &derror); dbus_error_free (&derror); goto out; break; diff --git a/test/glib/Makefile.am b/test/glib/Makefile.am index 77ee1906..04d9c644 100644 --- a/test/glib/Makefile.am +++ b/test/glib/Makefile.am @@ -61,7 +61,7 @@ my-object-marshal.h: Makefile my-object-marshal.list CLEANFILES = $(BUILT_SOURCES) -test_service_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la +test_service_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la $(DBUS_GLIB_THREADS_LIBS) else ### not building tests diff --git a/test/glib/test-dbus-glib.c b/test/glib/test-dbus-glib.c index e8cb74af..fd71d743 100644 --- a/test/glib/test-dbus-glib.c +++ b/test/glib/test-dbus-glib.c @@ -441,7 +441,8 @@ main (int argc, char **argv) if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID) != FALSE) lose ("ThrowError call unexpectedly succeeded!"); if (!dbus_g_error_has_name (error, "org.freedesktop.DBus.Tests.MyObject.Foo")) - lose ("ThrowError call returned unexpected error %s", dbus_g_error_get_name (error)); + lose ("ThrowError call returned unexpected error \"%s\": %s", dbus_g_error_get_name (error), + error->message); g_print ("ThrowError failed (as expected) returned error: %s\n", error->message); g_clear_error (&error); @@ -490,6 +491,13 @@ main (int argc, char **argv) if (v_UINT32_2 != 43) lose ("(wrapped) increment call returned %d, should be 43", v_UINT32_2); + v_UINT32_2 = 0; + if (!org_freedesktop_DBus_Tests_MyObject_async_increment (proxy, 42, &v_UINT32_2, &error)) + lose_gerror ("Failed to complete (wrapped) AsyncIncrement call", error); + + if (v_UINT32_2 != 43) + lose ("(wrapped) async increment call returned %d, should be 43", v_UINT32_2); + g_print ("Calling (wrapped) throw_error\n"); if (org_freedesktop_DBus_Tests_MyObject_throw_error (proxy, &error) != FALSE) lose ("(wrapped) ThrowError call unexpectedly succeeded!"); @@ -497,6 +505,12 @@ main (int argc, char **argv) g_print ("(wrapped) ThrowError failed (as expected) returned error: %s\n", error->message); g_clear_error (&error); + if (org_freedesktop_DBus_Tests_MyObject_async_throw_error (proxy, &error) != FALSE) + lose ("(wrapped) AsyncThrowError call unexpectedly succeeded!"); + + g_print ("(wrapped) AsyncThrowError failed (as expected) returned error: %s\n", error->message); + g_clear_error (&error); + g_print ("Calling (wrapped) uppercase\n"); if (!org_freedesktop_DBus_Tests_MyObject_uppercase (proxy, "foobar", &v_STRING_2, &error)) lose_gerror ("Failed to complete (wrapped) Uppercase call", error); diff --git a/test/glib/test-service-glib.c b/test/glib/test-service-glib.c index 9d5dfcc8..84b57c68 100644 --- a/test/glib/test-service-glib.c +++ b/test/glib/test-service-glib.c @@ -44,7 +44,9 @@ typedef enum MY_OBJECT_ERROR_BAR } MyObjectError; -#define MY_OBJECT_ERROR my_object_error_quark () +#define MY_OBJECT_ERROR (my_object_error_quark ()) + +#define MY_TYPE_ERROR (my_object_error_get_type ()) gboolean my_object_do_nothing (MyObject *obj, GError **error); @@ -85,10 +87,16 @@ gboolean my_object_emit_frobnicate (MyObject *obj, GError **error); gboolean my_object_terminate (MyObject *obj, GError **error); +gboolean my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context); + +gboolean my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context); + #include "test-service-glib-glue.h" GQuark my_object_error_quark (void); +GType my_object_error_get_type (void); + /* Properties */ enum { @@ -231,6 +239,30 @@ my_object_error_quark (void) return quark; } +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +my_object_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) + { + static const GEnumValue values[] = + { + + ENUM_ENTRY (MY_OBJECT_ERROR_FOO, "Foo"), + ENUM_ENTRY (MY_OBJECT_ERROR_BAR, "Bar"), + { 0, 0, 0 } + }; + + etype = g_enum_register_static ("MyObjectError", values); + } + + return etype; +} + static GObject *obj; static GObject *obj2; @@ -250,9 +282,11 @@ my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error) gboolean my_object_throw_error (MyObject *obj, GError **error) { - dbus_g_error_set (error, - "org.freedesktop.DBus.Tests.MyObject.Foo", - "this method always loses"); + g_set_error (error, + MY_OBJECT_ERROR, + MY_OBJECT_ERROR_FOO, + "%s", + "this method always loses"); return FALSE; } @@ -464,6 +498,53 @@ my_object_emit_signal2 (MyObject *obj, GError **error) return TRUE; } +typedef struct { + gint32 x; + DBusGMethodInvocation *context; +} IncrementData; + +static gboolean +do_async_increment (IncrementData *data) +{ + gint32 newx = data->x + 1; + dbus_g_method_return (data->context, newx); + g_free (data); + return FALSE; +} + +gboolean +my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context) +{ + IncrementData *data = g_new0 (IncrementData, 1); + data->x = x; + data->context = context; + g_idle_add ((GSourceFunc)do_async_increment, data); + return TRUE; +} + +static gboolean +do_async_error (IncrementData *data) +{ + GError *error; + error = g_error_new (MY_OBJECT_ERROR, + MY_OBJECT_ERROR_FOO, + "%s", + "this method always loses"); + dbus_g_method_return_error (data->context, error); + g_free (data); + return FALSE; +} + +gboolean +my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context) +{ + IncrementData *data = g_new0(IncrementData, 1); + data->context = context; + g_idle_add ((GSourceFunc)do_async_error, data); + return TRUE; +} + + static GMainLoop *loop; gboolean @@ -484,6 +565,14 @@ main (int argc, char **argv) guint32 request_name_ret; g_type_init (); + g_thread_init (NULL); dbus_g_thread_init (); + + dbus_g_object_type_install_info (MY_TYPE_OBJECT, + &dbus_glib_my_object_object_info); + + dbus_g_error_domain_register (MY_OBJECT_ERROR, + NULL, + MY_TYPE_ERROR); g_printerr ("Launching test-service-glib\n"); @@ -506,8 +595,6 @@ main (int argc, char **argv) obj = g_object_new (MY_TYPE_OBJECT, NULL); obj2 = g_object_new (MY_TYPE_OBJECT, NULL); - dbus_g_object_type_install_info (MY_TYPE_OBJECT, - &dbus_glib_my_object_object_info); dbus_g_connection_register_g_object (connection, "/org/freedesktop/DBus/Tests/MyTestObject", obj); diff --git a/test/glib/test-service-glib.xml b/test/glib/test-service-glib.xml index 83240b47..58058626 100644 --- a/test/glib/test-service-glib.xml +++ b/test/glib/test-service-glib.xml @@ -77,6 +77,16 @@ + + + + + + + + + + -- cgit