diff options
73 files changed, 7235 insertions, 1503 deletions
diff --git a/backends/telepathy/Makefile.am b/backends/telepathy/Makefile.am index d22d9697..6e036d1a 100644 --- a/backends/telepathy/Makefile.am +++ b/backends/telepathy/Makefile.am @@ -17,7 +17,7 @@ telepathy_la_VALAFLAGS = \ --pkg gee-0.8 \ --pkg gio-2.0 \ --pkg gobject-2.0 \ - --pkg telepathy-glib \ + --pkg telepathy-glib-1 \ $(NULL) backenddir = $(BACKEND_DIR)/telepathy diff --git a/backends/telepathy/lib/Makefile.am b/backends/telepathy/lib/Makefile.am index 0d32f81f..480d2703 100644 --- a/backends/telepathy/lib/Makefile.am +++ b/backends/telepathy/lib/Makefile.am @@ -78,8 +78,8 @@ tp-lowlevel.vapi: TpLowlevel-$(API_VERSION_DOT).gir $(AM_V_GEN)$(VAPIGEN) $(VAPIGENFLAGS) \ --library tp-lowlevel \ --pkg gio-2.0 \ - --pkg telepathy-glib \ - TpLowlevel-$(API_VERSION_DOT).gir + --pkg telepathy-glib-1 \ + TpLowlevel-$(API_VERSION_DOT).gir && sed -i "s/Tp\./TelepathyGLib\./g" $@ touch $@ endif @@ -156,7 +156,7 @@ libtp_zeitgeist_la_VALAFLAGS = \ --pkg gio-2.0 \ --pkg gee-0.8 \ --pkg zeitgeist-2.0 \ - --pkg telepathy-glib \ + --pkg telepathy-glib-1 \ --pkg folks \ --pkg build-conf \ --library tp-zeitgeist \ @@ -226,7 +226,7 @@ libfolks_telepathy_la_VALAFLAGS = \ --pkg gobject-2.0 \ --pkg gio-2.0 \ --pkg gee-0.8 \ - --pkg telepathy-glib \ + --pkg telepathy-glib-1 \ --includedir folks \ --library folks-telepathy \ --vapi folks-telepathy.vapi \ diff --git a/backends/telepathy/lib/folks-telepathy-uninstalled.pc.in b/backends/telepathy/lib/folks-telepathy-uninstalled.pc.in index c3a70c3e..81dcdeb5 100644 --- a/backends/telepathy/lib/folks-telepathy-uninstalled.pc.in +++ b/backends/telepathy/lib/folks-telepathy-uninstalled.pc.in @@ -7,6 +7,6 @@ vapidir=@abs_top_srcdir@/folks Name: Folks Telepathy support library (uninstalled copy) Description: Telepathy support library for the Folks meta-contacts library Version: @VERSION@ -Requires: folks glib-2.0 gobject-2.0 gee-0.8 telepathy-glib >= 0.11.11 +Requires: folks glib-2.0 gobject-2.0 gee-0.8 telepathy-glib-1 >= 0.99.1 Libs: ${abs_top_builddir}/backends/telepathy/libfolks-telepathy.la Cflags: -I${abs_top_srcdir} -I${abs_top_srcdir}/backends/telepathy -I${abs_top_builddir} diff --git a/backends/telepathy/lib/folks-telepathy.deps b/backends/telepathy/lib/folks-telepathy.deps index dec8d50a..8ecb0884 100644 --- a/backends/telepathy/lib/folks-telepathy.deps +++ b/backends/telepathy/lib/folks-telepathy.deps @@ -1,4 +1,4 @@ glib-2.0 gobject-2.0 folks -telepathy-glib +telepathy-glib-1 diff --git a/backends/telepathy/lib/folks-telepathy.pc.in b/backends/telepathy/lib/folks-telepathy.pc.in index 3e569160..1e5d8999 100644 --- a/backends/telepathy/lib/folks-telepathy.pc.in +++ b/backends/telepathy/lib/folks-telepathy.pc.in @@ -10,6 +10,6 @@ vapidir=@datadir@/vala/vapi Name: Folks Telepathy support library Description: Telepathy support library for the Folks meta-contacts library Version: @VERSION@ -Requires: folks glib-2.0 gobject-2.0 gee-0.8 telepathy-glib >= 0.11.11 +Requires: folks glib-2.0 gobject-2.0 gee-0.8 telepathy-glib-1 >= 0.99.1 Libs: -L${libdir} -lfolks-telepathy Cflags: -I${includedir} diff --git a/backends/telepathy/lib/tp-lowlevel.c b/backends/telepathy/lib/tp-lowlevel.c index da5052c2..d803e0f8 100644 --- a/backends/telepathy/lib/tp-lowlevel.c +++ b/backends/telepathy/lib/tp-lowlevel.c @@ -27,6 +27,7 @@ #include <glib/gi18n.h> #include <gio/gio.h> #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include "tp-lowlevel.h" diff --git a/backends/telepathy/lib/tpf-persona-store.vala b/backends/telepathy/lib/tpf-persona-store.vala index b5b0ac6e..63a5b00d 100644 --- a/backends/telepathy/lib/tpf-persona-store.vala +++ b/backends/telepathy/lib/tpf-persona-store.vala @@ -395,8 +395,8 @@ public class Tpf.PersonaStore : Folks.PersonaStore /* We do not trust local-xmpp or IRC at all, since Persona UIDs can be * faked by just changing hostname/username or nickname. */ - if (account.get_protocol () == "local-xmpp" || - account.get_protocol () == "irc") + if (account.get_protocol_name () == "local_xmpp" || + account.get_protocol_name () == "irc") this.trust_level = PersonaStoreTrust.NONE; else this.trust_level = PersonaStoreTrust.PARTIAL; @@ -487,14 +487,14 @@ public class Tpf.PersonaStore : Folks.PersonaStore * contacts. */ var factory = this._account_manager.get_factory (); factory.add_contact_features ({ - ContactFeature.ALIAS, - ContactFeature.AVATAR_DATA, - ContactFeature.AVATAR_TOKEN, - ContactFeature.CAPABILITIES, - ContactFeature.CLIENT_TYPES, - ContactFeature.PRESENCE, - ContactFeature.CONTACT_INFO, - ContactFeature.CONTACT_GROUPS + Contact.get_feature_quark_alias (), + Contact.get_feature_quark_avatar_data (), + Contact.get_feature_quark_avatar_token (), + Contact.get_feature_quark_capabilities (), + Contact.get_feature_quark_client_types (), + Contact.get_feature_quark_presence (), + Contact.get_feature_quark_contact_info (), + Contact.get_feature_quark_contact_groups (), }); this._account_manager.invalidated.connect ( @@ -511,7 +511,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore this._remove_store (this._persona_set); } }); - this._account_manager.account_validity_changed.connect ( + this._account_manager.account_usability_changed.connect ( (a, valid) => { if (!valid && this.account == a) @@ -762,11 +762,11 @@ public class Tpf.PersonaStore : Folks.PersonaStore 0 }); - if (!this.account.connection.has_interface_by_id ( - iface_quark_connection_interface_contact_list ())) + if (!this.account.connection.is_prepared ( + TelepathyGLib.Connection.get_feature_quark_contact_list ())) { debug ("Connection does not implement ContactList iface; " + - "legacy CMs are not supported any more."); + "skipping store with no contact list."); this._remove_store (this._persona_set); @@ -851,7 +851,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore if ((ci_flags & ContactInfoFlags.CAN_SET) != 0) { var field_specs = - connection.get_contact_info_supported_fields (); + connection.dup_contact_info_supported_fields (); foreach (var field_spec in field_specs) { /* XXX: we ignore the maximum count for each type of @@ -876,12 +876,12 @@ public class Tpf.PersonaStore : Folks.PersonaStore private async void _load_cache (HashSet<Persona>? old_personas) { /* Only load from the cache if the account is enabled and valid. */ - if (this.account.enabled == false || this.account.valid == false) + if (this.account.enabled == false || this.account.usable == false) { debug ("Skipping loading cache for Tpf.PersonaStore %p ('%s'): " + "enabled: %s, valid: %s.", this, this.id, this.account.enabled ? "yes" : "no", - this.account.valid ? "yes" : "no"); + this.account.usable ? "yes" : "no"); return; } @@ -973,7 +973,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore /* Only store/load the cache if the account is enabled and valid; * otherwise, the PersonaStore will get removed and the cache * deleted later anyway. */ - if (!this.account.enabled || !this.account.valid) + if (!this.account.enabled || !this.account.usable) { debug ("Skipping storing cache for Tpf.PersonaStore %p (ā%sā) as " + "its TpAccount is disabled or invalid.", this, this.id); @@ -1680,7 +1680,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore private async void _populate_counters () { this._zg_controller = new FolksTpZeitgeist.Controller (this, - this.account.protocol, (p, dt) => + this.account.protocol_name, (p, dt) => { var persona = p as Tpf.Persona; assert (persona != null); diff --git a/backends/telepathy/lib/tpf-persona.vala b/backends/telepathy/lib/tpf-persona.vala index 6a3cf550..4d9572e5 100644 --- a/backends/telepathy/lib/tpf-persona.vala +++ b/backends/telepathy/lib/tpf-persona.vala @@ -765,10 +765,10 @@ public class Tpf.Persona : Folks.Persona, * interface along with the code in * Kf.Persona.linkable_property_to_links(), but that depends on * bgo#624842 being fixed. */ - iid: account.get_protocol () + ":" + id, + iid: account.get_protocol_name () + ":" + id, uid: uid, store: store, - is_user: contact.handle == connection.self_handle); + is_user: contact == connection.self_contact); debug ("Created new Tpf.Persona '%s' for service-specific UID '%s': %p", uid, id, this); @@ -815,9 +815,9 @@ public class Tpf.Persona : Folks.Persona, try { var im_addr = ImDetails.normalise_im_address (this.display_id, - account.get_protocol ()); + account.get_protocol_name ()); var im_fd = new ImFieldDetails (im_addr); - this._im_addresses.set (account.get_protocol (), im_fd); + this._im_addresses.set (account.get_protocol_name (), im_fd); } catch (ImDetailsError e) { @@ -974,7 +974,7 @@ public class Tpf.Persona : Folks.Persona, AbstractFieldDetails<string>.hash_static, AbstractFieldDetails<string>.equal_static); - var contact_info = contact.get_contact_info (); + var contact_info = contact.dup_contact_info (); foreach (var info in contact_info) { if (info.field_name == "") {} diff --git a/backends/telepathy/tp-backend.vala b/backends/telepathy/tp-backend.vala index f593604e..b119db19 100644 --- a/backends/telepathy/tp-backend.vala +++ b/backends/telepathy/tp-backend.vala @@ -84,8 +84,8 @@ public class Folks.Backends.Tp.Backend : Folks.Backend PersonaStore[] removed_stores = {}; /* First handle adding any missing persona stores. */ - GLib.List<unowned Account> accounts = - this._account_manager.get_valid_accounts (); + GLib.List<Account> accounts = + this._account_manager.dup_usable_accounts (); foreach (Account account in accounts) { string id = account.get_object_path (); @@ -170,11 +170,11 @@ public class Folks.Backends.Tp.Backend : Folks.Backend yield this._account_manager.prepare_async (null); this._account_manager.account_enabled.connect ( this._account_enabled_cb); - this._account_manager.account_validity_changed.connect ( - this._account_validity_changed_cb); + this._account_manager.account_usability_changed.connect ( + this._account_usability_changed_cb); - GLib.List<unowned Account> accounts = - this._account_manager.get_valid_accounts (); + GLib.List<Account> accounts = + this._account_manager.dup_usable_accounts (); foreach (Account account in accounts) { this._account_enabled_cb (account); @@ -210,8 +210,8 @@ public class Folks.Backends.Tp.Backend : Folks.Backend this._account_manager.account_enabled.disconnect ( this._account_enabled_cb); - this._account_manager.account_validity_changed.disconnect ( - this._account_validity_changed_cb); + this._account_manager.account_usability_changed.disconnect ( + this._account_usability_changed_cb); this._account_manager = null; this._is_quiescent = false; @@ -226,7 +226,7 @@ public class Folks.Backends.Tp.Backend : Folks.Backend } } - private void _account_validity_changed_cb (Account account, bool valid) + private void _account_usability_changed_cb (Account account, bool valid) { if (valid) this._account_enabled_cb (account); diff --git a/configure.ac b/configure.ac index d00dc945..0fa03951 100644 --- a/configure.ac +++ b/configure.ac @@ -159,7 +159,7 @@ AS_IF([test "x$enable_libsocialweb_backend" != "xno"], [ have_libsocialweb_backend="yes", have_libsocialweb_backend="no") AS_IF([test "x$have_libsocialweb_backend" = "xyes" -a \ "x$enable_vala" = "xyes"], [ - VALA_CHECK_PACKAGES([telepathy-glib + VALA_CHECK_PACKAGES([telepathy-glib-1 gio-2.0 gee-0.8 libsocialweb-client], @@ -209,10 +209,13 @@ PKG_CHECK_MODULES([DBUS_GLIB], [dbus-glib-1 dbus-1]) PKG_CHECK_MODULES([GEE], [gee-0.8 >= $GEE_REQUIRED]) -TP_GLIB_REQUIRED=0.19.0 +TP_GLIB_REQUIRED=0.99.1 AS_IF([test x$enable_telepathy_backend = xyes], [ - PKG_CHECK_MODULES([TP_GLIB], [telepathy-glib >= $TP_GLIB_REQUIRED])]) + PKG_CHECK_MODULES([TP_GLIB], [ + telepathy-glib-1 >= $TP_GLIB_REQUIRED + telepathy-glib-1-dbus >= $TP_GLIB_REQUIRED + ])]) case "x$enable_zeitgeist" in xyes) AS_IF([test x$enable_telepathy_backend = xyes], @@ -341,7 +344,7 @@ AS_IF([test "x$enable_vala" = "xyes"], [ gee-0.8]) AS_IF([test x$enable_telepathy_backend = xyes], [ - VALA_CHECK_PACKAGES([telepathy-glib]) + VALA_CHECK_PACKAGES([telepathy-glib-1]) AS_IF([test "x$have_zeitgeist" == "xyes"], [ VALA_CHECK_PACKAGES([zeitgeist-2.0]) ]) diff --git a/docs/Makefile.am b/docs/Makefile.am index d94b21a7..56ece334 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -135,7 +135,7 @@ folks_telepathy_doc_deps = \ gmodule-2.0 \ gio-2.0 \ gee-0.8 \ - telepathy-glib \ + telepathy-glib-1 \ zeitgeist-2.0 \ tp-lowlevel \ build-conf \ diff --git a/folks/folks-uninstalled.pc.in b/folks/folks-uninstalled.pc.in index 642d8015..a4db1a70 100644 --- a/folks/folks-uninstalled.pc.in +++ b/folks/folks-uninstalled.pc.in @@ -7,6 +7,6 @@ vapidir=@abs_top_srcdir@/folks Name: Folks (uninstalled copy) Description: The Folks meta-contacts library Version: @VERSION@ -Requires: glib-2.0 gobject-2.0 gee-0.8 telepathy-glib >= 0.11.11 +Requires: glib-2.0 gobject-2.0 gee-0.8 telepathy-glib-1 >= 0.99.1 Libs: ${abs_top_builddir}/folks/libfolks.la Cflags: -I${abs_top_srcdir} -I${abs_top_builddir} diff --git a/tests/folks/aggregation.vala b/tests/folks/aggregation.vala index 22946bb0..410d8f78 100644 --- a/tests/folks/aggregation.vala +++ b/tests/folks/aggregation.vala @@ -26,7 +26,7 @@ public class AggregationTests : TpfTest.MixedTestCase private HashSet<string> _default_personas; private static string iid_prefix = - "telepathy:/org/freedesktop/Telepathy/Account/cm/protocol/account:"; + "telepathy:/im/telepathy1/Account/cm/protocol/account:"; private string olivier_sha1 = Checksum.compute_for_string (ChecksumType.SHA1, iid_prefix + "olivier@example.com"); diff --git a/tests/lib/telepathy/contactlist/Makefile.am b/tests/lib/telepathy/contactlist/Makefile.am index 05d23f63..b9b69107 100644 --- a/tests/lib/telepathy/contactlist/Makefile.am +++ b/tests/lib/telepathy/contactlist/Makefile.am @@ -11,7 +11,7 @@ VAPIGENFLAGS += \ --pkg gee-0.8 \ --pkg gmodule-2.0 \ --pkg dbus-glib-1 \ - --pkg telepathy-glib \ + --pkg telepathy-glib-1 \ $(NULL) noinst_LTLIBRARIES = libtp-test-contactlist.la @@ -36,8 +36,8 @@ libtp_test_contactlist_la_SOURCES = \ simple-account-manager.h \ simple-conn.c \ simple-conn.h \ - textchan-null.c \ - textchan-null.h \ + echo-chan.c \ + echo-chan.h \ util.c \ util.h \ $(NULL) @@ -84,7 +84,7 @@ tp-test-contactlist.vapi: tp-test-contactlist.gir tp-test-contactlist.deps @test x$(srcdir) = x. || cp $(srcdir)/tp-test-contactlist.deps . $(MAKE) $(AM_MAKEFLAGS) tp-test-contactlist.gir $(AM_V_GEN)$(VAPIGEN) $(VAPIGENFLAGS) --library tp-test-contactlist \ - tp-test-contactlist.gir + tp-test-contactlist.gir && sed -i "s/Tp\./TelepathyGLib\./g" $@ touch $@ endif diff --git a/tests/lib/telepathy/contactlist/backend.c b/tests/lib/telepathy/contactlist/backend.c index b7193dc2..243b4a6b 100644 --- a/tests/lib/telepathy/contactlist/backend.c +++ b/tests/lib/telepathy/contactlist/backend.c @@ -20,9 +20,8 @@ #include <config.h> #include <glib.h> -#include <telepathy-glib/base-connection.h> -#include <telepathy-glib/dbus.h> -#include <telepathy-glib/svc-account.h> +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include "simple-account.h" #include "simple-account-manager.h" @@ -133,7 +132,7 @@ void tp_tests_backend_set_up (TpTestsBackend *self) { TpTestsBackendPrivate *priv = self->priv; - TpSimpleClientFactory *factory; + TpClientFactory *factory; GError *error = NULL; /* Override the handler set in the general Folks.TestCase class */ @@ -160,7 +159,7 @@ tp_tests_backend_set_up (TpTestsBackend *self) priv->client_am = tp_account_manager_dup (); factory = tp_proxy_get_factory (priv->client_am); - tp_simple_client_factory_add_contact_features_varargs (factory, + tp_client_factory_add_contact_features_varargs (factory, TP_CONTACT_FEATURE_ALIAS, TP_CONTACT_FEATURE_AVATAR_DATA, TP_CONTACT_FEATURE_AVATAR_TOKEN, @@ -169,7 +168,7 @@ tp_tests_backend_set_up (TpTestsBackend *self) TP_CONTACT_FEATURE_PRESENCE, TP_CONTACT_FEATURE_CONTACT_INFO, TP_CONTACT_FEATURE_CONTACT_GROUPS, - TP_CONTACT_FEATURE_INVALID); + 0); } static void @@ -268,7 +267,7 @@ tp_tests_backend_add_account (TpTestsBackend *self, const gchar *account) { TpTestsBackendPrivate *priv = self->priv; - TpSimpleClientFactory *factory; + TpClientFactory *factory; AccountData *data; gchar *conn_path; GError *error = NULL; @@ -286,7 +285,7 @@ tp_tests_backend_add_account (TpTestsBackend *self, g_assert_no_error (error); factory = tp_proxy_get_factory (priv->client_am); - data->client_conn = tp_simple_client_factory_ensure_connection (factory, + data->client_conn = tp_client_factory_ensure_connection (factory, conn_path, NULL, &error); g_assert_no_error (error); diff --git a/tests/lib/telepathy/contactlist/broken-client-types-conn.c b/tests/lib/telepathy/contactlist/broken-client-types-conn.c new file mode 100644 index 00000000..0ffd9929 --- /dev/null +++ b/tests/lib/telepathy/contactlist/broken-client-types-conn.c @@ -0,0 +1,65 @@ +/* + * broken-client-types-conn.c - a connection with a broken client + * types implementation which inexplicably returns presence information! + * + * Copyright Ā© 2011 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "broken-client-types-conn.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +G_DEFINE_TYPE_WITH_CODE (TpTestsBrokenClientTypesConnection, + tp_tests_broken_client_types_connection, + TP_TESTS_TYPE_CONTACTS_CONNECTION, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CLIENT_TYPES, + NULL); + ); + +static void +tp_tests_broken_client_types_connection_init ( + TpTestsBrokenClientTypesConnection *self) +{ +} + +static void +broken_fill_client_types ( + GObject *object, + const GArray *contacts, + GHashTable *attributes) +{ + guint i; + + for (i = 0; i < contacts->len; i++) + { + TpHandle handle = g_array_index (contacts, guint, i); + /* Muahaha. Actually we add Presence information. */ + GValueArray *presence = tp_value_array_build (3, + G_TYPE_UINT, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, + G_TYPE_STRING, "available", + G_TYPE_STRING, "hi mum!", + G_TYPE_INVALID); + + tp_contacts_mixin_set_contact_attribute (attributes, + handle, + TP_TOKEN_CONNECTION_INTERFACE_PRESENCE_PRESENCE, + tp_g_value_slice_new_take_boxed (G_TYPE_VALUE_ARRAY, presence)); + } +} + +static void +tp_tests_broken_client_types_connection_class_init ( + TpTestsBrokenClientTypesConnectionClass *klass) +{ + TpTestsContactsConnectionClass *cc_class = + TP_TESTS_CONTACTS_CONNECTION_CLASS (klass); + + cc_class->fill_client_types = broken_fill_client_types; +} diff --git a/tests/lib/telepathy/contactlist/broken-client-types-conn.h b/tests/lib/telepathy/contactlist/broken-client-types-conn.h new file mode 100644 index 00000000..ad36d7d5 --- /dev/null +++ b/tests/lib/telepathy/contactlist/broken-client-types-conn.h @@ -0,0 +1,50 @@ +/* + * broken-client-types-conn.h - header for a connection with a broken client + * types implementation which inexplicably returns presence information! + * + * Copyright Ā© 2011 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef TP_TESTS_BROKEN_CLIENT_TYPES_CONN_H +#define TP_TESTS_BROKEN_CLIENT_TYPES_CONN_H + +#include "contacts-conn.h" + +typedef struct _TpTestsBrokenClientTypesConnection TpTestsBrokenClientTypesConnection; +typedef struct _TpTestsBrokenClientTypesConnectionClass TpTestsBrokenClientTypesConnectionClass; +typedef struct _TpTestsBrokenClientTypesConnectionPrivate TpTestsBrokenClientTypesConnectionPrivate; + +struct _TpTestsBrokenClientTypesConnectionClass { + TpTestsContactsConnectionClass parent_class; +}; + +struct _TpTestsBrokenClientTypesConnection { + TpTestsContactsConnection parent; + + TpTestsBrokenClientTypesConnectionPrivate *priv; +}; + +GType tp_tests_broken_client_types_connection_get_type (void); + +/* HI MUM */ +#define TP_TESTS_TYPE_BROKEN_CLIENT_TYPES_CONNECTION \ + (tp_tests_broken_client_types_connection_get_type ()) +#define TP_TESTS_BROKEN_CLIENT_TYPES_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_BROKEN_CLIENT_TYPES_CONNECTION, \ + TpTestsBrokenClientTypesConnection)) +#define TP_TESTS_BROKEN_CLIENT_TYPES_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_BROKEN_CLIENT_TYPES_CONNECTION, \ + TpTestsBrokenClientTypesConnectionClass)) +#define TP_TESTS_IS_BROKEN_CLIENT_TYPES_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_BROKEN_CLIENT_TYPES_CONNECTION)) +#define TP_TESTS_IS_BROKEN_CLIENT_TYPES_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_BROKEN_CLIENT_TYPES_CONNECTION)) +#define TP_TESTS_BROKEN_CLIENT_TYPES_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_BROKEN_CLIENT_TYPES_CONNECTION, \ + TpTestsBrokenClientTypesConnectionClass)) + +#endif // TP_TESTS_BROKEN_CLIENT_TYPES_CONN_H diff --git a/tests/lib/telepathy/contactlist/bug-19101-conn.c b/tests/lib/telepathy/contactlist/bug-19101-conn.c new file mode 100644 index 00000000..52a4b683 --- /dev/null +++ b/tests/lib/telepathy/contactlist/bug-19101-conn.c @@ -0,0 +1,74 @@ +/* + * bug-19101-conn.c - a broken connection to reproduce bug #19101 + * + * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2008 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "bug-19101-conn.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +#include "debug.h" + +static void contacts_iface_init (gpointer g_iface, gpointer iface_data); + +G_DEFINE_TYPE_WITH_CODE (TpTestsBug19101Connection, + tp_tests_bug19101_connection, TP_TESTS_TYPE_CONTACTS_CONNECTION, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS, + contacts_iface_init); + ) + +static void +tp_tests_bug19101_connection_init (TpTestsBug19101Connection *self) +{ +} + +static void +tp_tests_bug19101_connection_class_init (TpTestsBug19101ConnectionClass *klass) +{ +} + +/* A broken implementation of GetContactByID, which returns an empty dict + * of attributes for each id. + */ +static void +tp_tests_bug19101_connection_get_contact_by_id ( + TpSvcConnectionInterfaceContacts *iface, + const gchar *id, + const char **interfaces, + DBusGMethodInvocation *context) +{ + TpBaseConnection *base_conn = TP_BASE_CONNECTION (iface); + TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( + base_conn, TP_HANDLE_TYPE_CONTACT); + TpHandle handle; + GHashTable *table; + + handle = tp_handle_ensure (contact_repo, id, NULL, NULL); + table = g_hash_table_new (NULL, NULL); + + tp_svc_connection_interface_contacts_return_from_get_contact_by_id ( + context, handle, table); + + g_hash_table_unref (table); +} + +static void +contacts_iface_init (gpointer g_iface, gpointer iface_data) +{ + TpSvcConnectionInterfaceContactsClass *klass = + (TpSvcConnectionInterfaceContactsClass *) g_iface; + +#define IMPLEMENT(x) tp_svc_connection_interface_contacts_implement_##x ( \ + klass, tp_tests_bug19101_connection_##x) + IMPLEMENT(get_contact_by_id); +#undef IMPLEMENT +} diff --git a/tests/lib/telepathy/contactlist/bug-19101-conn.h b/tests/lib/telepathy/contactlist/bug-19101-conn.h new file mode 100644 index 00000000..23b670e3 --- /dev/null +++ b/tests/lib/telepathy/contactlist/bug-19101-conn.h @@ -0,0 +1,51 @@ +/* + * bug-19101-conn.h - header for a broken connection to reproduce bug #19101 + * + * Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2007-2008 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_BUG19101_CONN_H__ +#define __TP_TESTS_BUG19101_CONN_H__ + +#include "contacts-conn.h" + +G_BEGIN_DECLS + +typedef struct _TpTestsBug19101Connection TpTestsBug19101Connection; +typedef struct _TpTestsBug19101ConnectionClass TpTestsBug19101ConnectionClass; + +struct _TpTestsBug19101ConnectionClass { + TpTestsContactsConnectionClass parent_class; +}; + +struct _TpTestsBug19101Connection { + TpTestsContactsConnection parent; +}; + +GType tp_tests_bug19101_connection_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_BUG19101_CONNECTION \ + (tp_tests_bug19101_connection_get_type ()) +#define BUG_19101_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_BUG19101_CONNECTION, \ + TpTestsBug19101Connection)) +#define BUG_19101_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_BUG19101_CONNECTION, \ + TpTestsBug19101ConnectionClass)) +#define BUG_19101_IS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_BUG19101_CONNECTION)) +#define BUG_19101_IS_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_BUG19101_CONNECTION)) +#define BUG_19101_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_BUG19101_CONNECTION, \ + TpTestsBug19101ConnectionClass)) + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_BUG19101_CONN_H__ */ diff --git a/tests/lib/telepathy/contactlist/contact-list-manager.c b/tests/lib/telepathy/contactlist/contact-list-manager.c index b816673a..bce8e21a 100644 --- a/tests/lib/telepathy/contactlist/contact-list-manager.c +++ b/tests/lib/telepathy/contactlist/contact-list-manager.c @@ -26,8 +26,7 @@ struct _TpTestsContactListManagerPrivate GHashTable *contact_details; TpHandleRepoIface *contact_repo; - TpHandleRepoIface *group_repo; - TpHandleSet *groups; + GHashTable *groups; }; static void contact_groups_iface_init (TpContactGroupListInterface *iface); @@ -49,7 +48,7 @@ typedef struct { TpSubscriptionState subscribe; TpSubscriptionState publish; gchar *publish_request; - TpHandleSet *groups; + GHashTable *groups; TpHandle handle; TpHandleRepoIface *contact_repo; @@ -61,7 +60,7 @@ contact_detail_destroy (gpointer p) ContactDetails *d = p; g_free (d->publish_request); - tp_handle_set_destroy (d->groups); + g_hash_table_unref (d->groups); g_slice_free (ContactDetails, d); } @@ -86,7 +85,7 @@ ensure_contact (TpTestsContactListManager *self, d->subscribe = TP_SUBSCRIPTION_STATE_NO; d->publish = TP_SUBSCRIPTION_STATE_NO; d->publish_request = NULL; - d->groups = tp_handle_set_new (self->priv->group_repo); + d->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); d->handle = handle; d->contact_repo = self->priv->contact_repo; @@ -117,7 +116,7 @@ close_all (TpTestsContactListManager *self) self->priv->status_changed_id = 0; } tp_clear_pointer (&self->priv->contact_details, g_hash_table_unref); - tp_clear_pointer (&self->priv->groups, tp_handle_set_destroy); + tp_clear_pointer (&self->priv->groups, g_hash_table_unref); } static void @@ -197,16 +196,15 @@ contact_list_dup_groups (TpBaseContactList *base) if (self->priv->groups != NULL) { - TpIntsetFastIter iter; - TpHandle group; + GHashTableIter iter; + gpointer name; - ret = g_ptr_array_sized_new (tp_handle_set_size (self->priv->groups) + 1); + ret = g_ptr_array_sized_new (g_hash_table_size (self->priv->groups) + 1); - tp_intset_fast_iter_init (&iter, tp_handle_set_peek (self->priv->groups)); - while (tp_intset_fast_iter_next (&iter, &group)) + g_hash_table_iter_init (&iter, self->priv->groups); + while (g_hash_table_iter_next (&iter, &name, NULL)) { - g_ptr_array_add (ret, g_strdup (tp_handle_inspect ( - self->priv->group_repo, group))); + g_ptr_array_add (ret, g_strdup (name)); } } else @@ -229,16 +227,15 @@ contact_list_dup_contact_groups (TpBaseContactList *base, if (d != NULL && d->groups != NULL) { - TpIntsetFastIter iter; - TpHandle group; + GHashTableIter iter; + gpointer name; - ret = g_ptr_array_sized_new (tp_handle_set_size (d->groups) + 1); + ret = g_ptr_array_sized_new (g_hash_table_size (d->groups) + 1); - tp_intset_fast_iter_init (&iter, tp_handle_set_peek (d->groups)); - while (tp_intset_fast_iter_next (&iter, &group)) + g_hash_table_iter_init (&iter, d->groups); + while (g_hash_table_iter_next (&iter, &name, NULL)) { - g_ptr_array_add (ret, g_strdup (tp_handle_inspect ( - self->priv->group_repo, group))); + g_ptr_array_add (ret, g_strdup (name)); } } else @@ -256,14 +253,13 @@ contact_list_dup_group_members (TpBaseContactList *base, const gchar *group) { TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (base); - TpHandleSet *set; - TpHandle group_handle; GHashTableIter iter; gpointer k, v; + TpHandleSet *set; set = tp_handle_set_new (self->priv->contact_repo); - group_handle = tp_handle_lookup (self->priv->group_repo, group, NULL, NULL); - if (G_UNLIKELY (group_handle == 0)) + + if (G_UNLIKELY (g_hash_table_lookup (self->priv->groups, group) == NULL)) { /* clearly it doesn't have members */ return set; @@ -275,13 +271,31 @@ contact_list_dup_group_members (TpBaseContactList *base, ContactDetails *d = v; if (d->groups != NULL && - tp_handle_set_is_member (d->groups, group_handle)) + g_hash_table_lookup (d->groups, group) != NULL) tp_handle_set_add (set, GPOINTER_TO_UINT (k)); } return set; } +static GPtrArray * +group_difference (GHashTable *left, + GHashTable *right) +{ + GHashTableIter iter; + GPtrArray *set = g_ptr_array_sized_new (g_hash_table_size (left)); + gpointer name; + + g_hash_table_iter_init (&iter, left); + while (g_hash_table_iter_next (&iter, &name, NULL)) + { + if (g_hash_table_lookup (right, name) == NULL) + g_ptr_array_add (set, name); + } + + return set; +} + static void contact_list_set_contact_groups_async (TpBaseContactList *base, TpHandle contact, @@ -292,25 +306,24 @@ contact_list_set_contact_groups_async (TpBaseContactList *base, { TpTestsContactListManager *self = TP_TESTS_CONTACT_LIST_MANAGER (base); ContactDetails *d; - TpIntset *set, *added_set, *removed_set; - GPtrArray *added_names, *removed_names; + GHashTable *tmp; + GPtrArray *added, *removed; GPtrArray *new_groups; - TpIntsetFastIter iter; - TpHandle group_handle; guint i; d = ensure_contact (self, contact); new_groups = g_ptr_array_new (); - set = tp_intset_new (); + /* make a hash table so we only have one difference function */ + tmp = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; i < n; i++) { - group_handle = tp_handle_ensure (self->priv->group_repo, names[i], NULL, NULL); - tp_intset_add (set, group_handle); + g_hash_table_insert (tmp, (gpointer) names[i], GUINT_TO_POINTER (1)); - if (!tp_handle_set_is_member (self->priv->groups, group_handle)) + if (g_hash_table_lookup (self->priv->groups, names[i]) == NULL) { - tp_handle_set_add (self->priv->groups, group_handle); + g_hash_table_insert (self->priv->groups, g_strdup (names[i]), + GUINT_TO_POINTER (1)); g_ptr_array_add (new_groups, (gchar *) names[i]); } } @@ -321,42 +334,30 @@ contact_list_set_contact_groups_async (TpBaseContactList *base, (const gchar * const *) new_groups->pdata, new_groups->len); } - added_set = tp_intset_difference (set, tp_handle_set_peek (d->groups)); - added_names = g_ptr_array_sized_new (tp_intset_size (added_set)); - tp_intset_fast_iter_init (&iter, added_set); - while (tp_intset_fast_iter_next (&iter, &group_handle)) - { - g_ptr_array_add (added_names, (gchar *) tp_handle_inspect ( - self->priv->group_repo, group_handle)); - } - tp_intset_destroy (added_set); + /* see which groups were added and which were removed */ + added = group_difference (tmp, d->groups); + removed = group_difference (d->groups, tmp); - removed_set = tp_intset_difference (tp_handle_set_peek (d->groups), set); - removed_names = g_ptr_array_sized_new (tp_intset_size (removed_set)); - tp_intset_fast_iter_init (&iter, removed_set); - while (tp_intset_fast_iter_next (&iter, &group_handle)) - { - g_ptr_array_add (removed_names, (gchar *) tp_handle_inspect ( - self->priv->group_repo, group_handle)); - } - tp_intset_destroy (removed_set); + g_hash_table_unref (tmp); - tp_handle_set_destroy (d->groups); - d->groups = tp_handle_set_new_from_intset (self->priv->group_repo, set); - tp_intset_destroy (set); + /* update the list of groups the contact thinks it has */ + g_hash_table_remove_all (d->groups); + for (i = 0; i < n; i++) + g_hash_table_insert (d->groups, g_strdup (names[i]), GUINT_TO_POINTER (1)); - if (added_names->len > 0 || removed_names->len > 0) + /* signal the change */ + if (added->len > 0 || removed->len > 0) { tp_base_contact_list_one_contact_groups_changed (base, contact, - (const gchar * const *) added_names->pdata, added_names->len, - (const gchar * const *) removed_names->pdata, removed_names->len); + (const gchar * const *) added->pdata, added->len, + (const gchar * const *) removed->pdata, removed->len); } tp_simple_async_report_success_in_idle ((GObject *) self, callback, user_data, contact_list_set_contact_groups_async); - g_ptr_array_unref (added_names); - g_ptr_array_unref (removed_names); + g_ptr_array_unref (added); + g_ptr_array_unref (removed); g_ptr_array_unref (new_groups); } @@ -551,9 +552,8 @@ constructed (GObject *object) self->priv->contact_repo = tp_base_connection_get_handles (self->priv->conn, TP_HANDLE_TYPE_CONTACT); - self->priv->group_repo = tp_base_connection_get_handles (self->priv->conn, - TP_HANDLE_TYPE_GROUP); - self->priv->groups = tp_handle_set_new (self->priv->group_repo); + self->priv->groups = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); } static void @@ -606,19 +606,17 @@ tp_tests_contact_list_manager_add_to_group (TpTestsContactListManager *self, { TpBaseContactList *base = TP_BASE_CONTACT_LIST (self); ContactDetails *d = ensure_contact (self, member); - TpHandle group_handle; - group_handle = tp_handle_ensure (self->priv->group_repo, - group_name, NULL, NULL); + g_hash_table_insert (d->groups, g_strdup (group_name), GUINT_TO_POINTER (1)); - if (!tp_handle_set_is_member (self->priv->groups, group_handle)) + if (g_hash_table_lookup (self->priv->groups, group_name) == NULL) { - tp_handle_set_add (self->priv->groups, group_handle); + g_hash_table_insert (self->priv->groups, g_strdup (group_name), + GUINT_TO_POINTER (1)); tp_base_contact_list_groups_created ((TpBaseContactList *) self, &group_name, 1); } - tp_handle_set_add (d->groups, group_handle); tp_base_contact_list_one_contact_groups_changed (base, member, &group_name, 1, NULL, 0); } @@ -629,14 +627,12 @@ tp_tests_contact_list_manager_remove_from_group (TpTestsContactListManager *self { TpBaseContactList *base = TP_BASE_CONTACT_LIST (self); ContactDetails *d = lookup_contact (self, member); - TpHandle group_handle; if (d == NULL) return; - group_handle = tp_handle_ensure (self->priv->group_repo, group_name, NULL, NULL); + g_hash_table_remove (d->groups, group_name); - tp_handle_set_remove (d->groups, group_handle); tp_base_contact_list_one_contact_groups_changed (base, member, NULL, 0, &group_name, 1); } diff --git a/tests/lib/telepathy/contactlist/contact-list-manager.h b/tests/lib/telepathy/contactlist/contact-list-manager.h index 8be787c3..bc44863c 100644 --- a/tests/lib/telepathy/contactlist/contact-list-manager.h +++ b/tests/lib/telepathy/contactlist/contact-list-manager.h @@ -12,7 +12,7 @@ #ifndef __TP_TESTS_CONTACT_LIST_MANAGER_H__ #define __TP_TESTS_CONTACT_LIST_MANAGER_H__ -#include <telepathy-glib/base-contact-list.h> +#include <telepathy-glib/telepathy-glib.h> G_BEGIN_DECLS diff --git a/tests/lib/telepathy/contactlist/contacts-conn.c b/tests/lib/telepathy/contactlist/contacts-conn.c index 6f308809..3ba50a20 100644 --- a/tests/lib/telepathy/contactlist/contacts-conn.c +++ b/tests/lib/telepathy/contactlist/contacts-conn.c @@ -15,19 +15,13 @@ #include <dbus/dbus-glib.h> -#include <telepathy-glib/interfaces.h> -#include <telepathy-glib/dbus.h> -#include <telepathy-glib/errors.h> -#include <telepathy-glib/gtypes.h> -#include <telepathy-glib/handle-repo-dynamic.h> -#include <telepathy-glib/util.h> +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include "debug.h" static void init_aliasing (gpointer, gpointer); static void init_avatars (gpointer, gpointer); -static void init_location (gpointer, gpointer); -static void init_contact_caps (gpointer, gpointer); static void init_contact_info (gpointer, gpointer); static void conn_avatars_properties_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data); @@ -41,13 +35,9 @@ G_DEFINE_TYPE_WITH_CODE (TpTestsContactsConnection, init_avatars); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_PRESENCE, tp_presence_mixin_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE, - tp_presence_mixin_simple_presence_iface_init) - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_LOCATION, - init_location) + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_LOCATION, NULL) G_IMPLEMENT_INTERFACE ( - TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, - init_contact_caps) + TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, NULL) G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_INFO, init_contact_info) G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS, @@ -402,11 +392,17 @@ constructed (GObject *object) if (parent_impl != NULL) parent_impl (object); + self->priv->list_manager = g_object_new (TP_TESTS_TYPE_CONTACT_LIST_MANAGER, + "connection", self, NULL); + tp_contacts_mixin_init (object, G_STRUCT_OFFSET (TpTestsContactsConnection, contacts_mixin)); tp_base_connection_register_with_contacts_mixin (base); if (self->priv->list_manager) - tp_base_contact_list_mixin_register_with_contacts_mixin (base); + { + tp_base_contact_list_mixin_register_with_contacts_mixin ( + TP_BASE_CONTACT_LIST (self->priv->list_manager), base); + } tp_contacts_mixin_add_contact_attributes_iface (object, TP_IFACE_CONNECTION_INTERFACE_ALIASING, aliasing_fill_contact_attributes); @@ -428,7 +424,7 @@ constructed (GObject *object) tp_presence_mixin_init (object, G_STRUCT_OFFSET (TpTestsContactsConnection, presence_mixin)); - tp_presence_mixin_simple_presence_register_with_contacts_mixin (object); + tp_presence_mixin_register_with_contacts_mixin (object); } static const TpPresenceStatusOptionalArgumentSpec can_have_message[] = { @@ -459,8 +455,7 @@ my_status_available (GObject *object, static GHashTable * my_get_contact_statuses (GObject *object, - const GArray *contacts, - GError **error) + const GArray *contacts) { TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object); GHashTable *result = g_hash_table_new_full (g_direct_hash, g_direct_equal, @@ -529,24 +524,13 @@ my_get_maximum_status_message_length_cb (GObject *obj) static GPtrArray * create_channel_managers (TpBaseConnection *conn) { - TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (conn); - GPtrArray *ret = g_ptr_array_sized_new (1); - - self->priv->list_manager = g_object_new (TP_TESTS_TYPE_CONTACT_LIST_MANAGER, - "connection", conn, NULL); - - g_ptr_array_add (ret, self->priv->list_manager); - - return ret; + return g_ptr_array_new (); } -static void -tp_tests_contacts_connection_class_init (TpTestsContactsConnectionClass *klass) +static GPtrArray * +tp_tests_contacts_get_interfaces_always_present (TpBaseConnection *base) { - TpBaseConnectionClass *base_class = - (TpBaseConnectionClass *) klass; - GObjectClass *object_class = (GObjectClass *) klass; - TpPresenceMixinClass *mixin_class; + GPtrArray *interfaces; static const gchar *interfaces_always_present[] = { TP_IFACE_CONNECTION_INTERFACE_ALIASING, TP_IFACE_CONNECTION_INTERFACE_AVATARS, @@ -554,13 +538,56 @@ tp_tests_contacts_connection_class_init (TpTestsContactsConnectionClass *klass) TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST, TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS, TP_IFACE_CONNECTION_INTERFACE_PRESENCE, - TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE, TP_IFACE_CONNECTION_INTERFACE_LOCATION, TP_IFACE_CONNECTION_INTERFACE_CLIENT_TYPES, TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, - TP_IFACE_CONNECTION_INTERFACE_REQUESTS, NULL }; + guint i; + + interfaces = TP_BASE_CONNECTION_CLASS ( + tp_tests_contacts_connection_parent_class)->get_interfaces_always_present (base); + + for (i = 0; interfaces_always_present[i] != NULL; i++) + g_ptr_array_add (interfaces, (gchar *) interfaces_always_present[i]); + + return interfaces; +} + +enum +{ + ALIASING_DP_ALIAS_FLAGS, +}; + +static void +aliasing_get_dbus_property (GObject *object, + GQuark interface, + GQuark name, + GValue *value, + gpointer user_data) +{ + switch (GPOINTER_TO_UINT (user_data)) + { + case ALIASING_DP_ALIAS_FLAGS: + g_value_set_uint (value, TP_CONNECTION_ALIAS_FLAG_USER_SET); + break; + + default: + g_assert_not_reached (); + } +} + +static void +tp_tests_contacts_connection_class_init (TpTestsContactsConnectionClass *klass) +{ + TpBaseConnectionClass *base_class = + (TpBaseConnectionClass *) klass; + GObjectClass *object_class = (GObjectClass *) klass; + TpPresenceMixinClass *mixin_class; + static TpDBusPropertiesMixinPropImpl aliasing_props[] = { + { "AliasFlags", GUINT_TO_POINTER (ALIASING_DP_ALIAS_FLAGS), NULL }, + { NULL } + }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_CONNECTION_INTERFACE_AVATARS, conn_avatars_properties_getter, @@ -572,6 +599,11 @@ tp_tests_contacts_connection_class_init (TpTestsContactsConnectionClass *klass) NULL, conn_contact_info_properties, }, + { TP_IFACE_CONNECTION_INTERFACE_ALIASING, + aliasing_get_dbus_property, + NULL, + aliasing_props, + }, { NULL } }; @@ -579,7 +611,7 @@ tp_tests_contacts_connection_class_init (TpTestsContactsConnectionClass *klass) object_class->finalize = finalize; g_type_class_add_private (klass, sizeof (TpTestsContactsConnectionPrivate)); - base_class->interfaces_always_present = interfaces_always_present; + base_class->get_interfaces_always_present = tp_tests_contacts_get_interfaces_always_present; base_class->create_channel_managers = create_channel_managers; tp_contacts_mixin_class_init (object_class, @@ -593,7 +625,7 @@ tp_tests_contacts_connection_class_init (TpTestsContactsConnectionClass *klass) mixin_class->get_maximum_status_message_length = my_get_maximum_status_message_length_cb; - tp_presence_mixin_simple_presence_init_dbus_properties (object_class); + tp_presence_mixin_init_dbus_properties (object_class); klass->properties_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, @@ -623,34 +655,23 @@ tp_tests_contacts_connection_change_aliases (TpTestsContactsConnection *self, const TpHandle *handles, const gchar * const *aliases) { - GPtrArray *structs = g_ptr_array_sized_new (n); + GHashTable *changes = g_hash_table_new (NULL, NULL); guint i; for (i = 0; i < n; i++) { - GValueArray *pair = g_value_array_new (2); - DEBUG ("contact#%u -> %s", handles[i], aliases[i]); g_hash_table_insert (self->priv->aliases, GUINT_TO_POINTER (handles[i]), g_strdup (aliases[i])); - g_value_array_append (pair, NULL); - g_value_init (pair->values + 0, G_TYPE_UINT); - g_value_set_uint (pair->values + 0, handles[i]); - - g_value_array_append (pair, NULL); - g_value_init (pair->values + 1, G_TYPE_STRING); - g_value_set_string (pair->values + 1, aliases[i]); - - g_ptr_array_add (structs, pair); + g_hash_table_insert (changes, + GUINT_TO_POINTER (handles[i]), (gchar *) aliases[i]); } - tp_svc_connection_interface_aliasing_emit_aliases_changed (self, - structs); + tp_svc_connection_interface_aliasing_emit_aliases_changed (self, changes); - g_ptr_array_foreach (structs, (GFunc) g_value_array_free, NULL); - g_ptr_array_unref (structs); + g_hash_table_unref (changes); } void @@ -793,60 +814,6 @@ tp_tests_contacts_connection_set_default_contact_info ( } static void -my_get_alias_flags (TpSvcConnectionInterfaceAliasing *aliasing, - DBusGMethodInvocation *context) -{ - TpBaseConnection *base = TP_BASE_CONNECTION (aliasing); - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - tp_svc_connection_interface_aliasing_return_from_get_alias_flags (context, - TP_CONNECTION_ALIAS_FLAG_USER_SET); -} - -static void -my_get_aliases (TpSvcConnectionInterfaceAliasing *aliasing, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (aliasing); - TpBaseConnection *base = TP_BASE_CONNECTION (aliasing); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - GHashTable *result; - GError *error = NULL; - guint i; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); - - for (i = 0; i < contacts->len; i++) - { - TpHandle handle = g_array_index (contacts, TpHandle, i); - const gchar *alias = g_hash_table_lookup (self->priv->aliases, - GUINT_TO_POINTER (handle)); - - if (alias == NULL) - g_hash_table_insert (result, GUINT_TO_POINTER (handle), - (gchar *) tp_handle_inspect (contact_repo, handle)); - else - g_hash_table_insert (result, GUINT_TO_POINTER (handle), - (gchar *) alias); - } - - tp_svc_connection_interface_aliasing_return_from_get_aliases (context, - result); - g_hash_table_unref (result); -} - -static void my_request_aliases (TpSvcConnectionInterfaceAliasing *aliasing, const GArray *contacts, DBusGMethodInvocation *context) @@ -950,105 +917,12 @@ init_aliasing (gpointer g_iface, #define IMPLEMENT(x) tp_svc_connection_interface_aliasing_implement_##x (\ klass, my_##x) - IMPLEMENT(get_alias_flags); IMPLEMENT(request_aliases); - IMPLEMENT(get_aliases); IMPLEMENT(set_aliases); #undef IMPLEMENT } static void -my_get_avatar_tokens (TpSvcConnectionInterfaceAvatars *avatars, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (avatars); - TpBaseConnection *base = TP_BASE_CONNECTION (avatars); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - GError *error = NULL; - GHashTable *result; - guint i; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); - - for (i = 0; i < contacts->len; i++) - { - TpHandle handle = g_array_index (contacts, TpHandle, i); - AvatarData *a = g_hash_table_lookup (self->priv->avatars, - GUINT_TO_POINTER (handle)); - - if (a == NULL || a->token == NULL) - { - /* we're expected to do a round-trip to the server to find out - * their token, so we have to give some sort of result. Assume - * no avatar, here */ - a = avatar_data_new (NULL, NULL, ""); - g_hash_table_insert (self->priv->avatars, - GUINT_TO_POINTER (handle), a); - tp_svc_connection_interface_avatars_emit_avatar_updated (self, - handle, a->token); - } - - g_hash_table_insert (result, GUINT_TO_POINTER (handle), - a->token); - } - - tp_svc_connection_interface_avatars_return_from_get_known_avatar_tokens ( - context, result); - g_hash_table_unref (result); -} - -static void -my_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *avatars, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (avatars); - TpBaseConnection *base = TP_BASE_CONNECTION (avatars); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - GError *error = NULL; - GHashTable *result; - guint i; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); - - for (i = 0; i < contacts->len; i++) - { - TpHandle handle = g_array_index (contacts, TpHandle, i); - AvatarData *a = g_hash_table_lookup (self->priv->avatars, - GUINT_TO_POINTER (handle)); - const gchar *token = a ? a->token : NULL; - - g_hash_table_insert (result, GUINT_TO_POINTER (handle), - (gchar *) (token != NULL ? token : "")); - } - - tp_svc_connection_interface_avatars_return_from_get_known_avatar_tokens ( - context, result); - g_hash_table_unref (result); -} - -static void my_request_avatars (TpSvcConnectionInterfaceAvatars *avatars, const GArray *contacts, DBusGMethodInvocation *context) @@ -1112,8 +986,6 @@ init_avatars (gpointer g_iface, #define IMPLEMENT(x) tp_svc_connection_interface_avatars_implement_##x (\ klass, my_##x) /* IMPLEMENT(get_avatar_requirements); */ - IMPLEMENT(get_avatar_tokens); - IMPLEMENT(get_known_avatar_tokens); /* IMPLEMENT(request_avatar); */ IMPLEMENT(request_avatars); /* IMPLEMENT(set_avatar); */ @@ -1121,113 +993,6 @@ init_avatars (gpointer g_iface, #undef IMPLEMENT } -static void -my_get_locations (TpSvcConnectionInterfaceLocation *avatars, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (avatars); - TpBaseConnection *base = TP_BASE_CONNECTION (avatars); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - GError *error = NULL; - GHashTable *result; - guint i; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); - - for (i = 0; i < contacts->len; i++) - { - TpHandle handle = g_array_index (contacts, TpHandle, i); - GHashTable *location = g_hash_table_lookup (self->priv->locations, - GUINT_TO_POINTER (handle)); - - if (location != NULL) - { - g_hash_table_insert (result, GUINT_TO_POINTER (handle), location); - } - } - - tp_svc_connection_interface_location_return_from_get_locations ( - context, result); - g_hash_table_unref (result); -} - -static void -init_location (gpointer g_iface, - gpointer iface_data) -{ - TpSvcConnectionInterfaceLocationClass *klass = g_iface; - -#define IMPLEMENT(x) tp_svc_connection_interface_location_implement_##x (\ - klass, my_##x) - IMPLEMENT(get_locations); -#undef IMPLEMENT -} - -static void -my_get_contact_capabilities (TpSvcConnectionInterfaceContactCapabilities *obj, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (obj); - TpBaseConnection *base = TP_BASE_CONNECTION (obj); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - GError *error = NULL; - GHashTable *result; - guint i; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); - - for (i = 0; i < contacts->len; i++) - { - TpHandle handle = g_array_index (contacts, TpHandle, i); - GPtrArray *arr = g_hash_table_lookup (self->priv->capabilities, - GUINT_TO_POINTER (handle)); - - if (arr != NULL) - { - g_hash_table_insert (result, GUINT_TO_POINTER (handle), arr); - } - } - - tp_svc_connection_interface_contact_capabilities_return_from_get_contact_capabilities ( - context, result); - - g_hash_table_unref (result); -} - -static void -init_contact_caps (gpointer g_iface, - gpointer iface_data) -{ - TpSvcConnectionInterfaceContactCapabilitiesClass *klass = g_iface; - -#define IMPLEMENT(x) tp_svc_connection_interface_contact_capabilities_implement_##x (\ - klass, my_##x) - IMPLEMENT(get_contact_capabilities); -#undef IMPLEMENT -} - static GPtrArray * lookup_contact_info (TpTestsContactsConnection *self, TpHandle handle) @@ -1351,92 +1116,3 @@ init_contact_info (gpointer g_iface, IMPLEMENT (set_contact_info); #undef IMPLEMENT } - -/* =============== Legacy version (no Contacts interface) ================= */ - -G_DEFINE_TYPE (TpTestsLegacyContactsConnection, - tp_tests_legacy_contacts_connection, TP_TESTS_TYPE_CONTACTS_CONNECTION); - -enum -{ - LEGACY_PROP_HAS_IMMORTAL_HANDLES = 1 -}; - -static void -legacy_contacts_connection_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) - { - case LEGACY_PROP_HAS_IMMORTAL_HANDLES: - /* Pretend we don't. */ - g_value_set_boolean (value, FALSE); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -tp_tests_legacy_contacts_connection_init (TpTestsLegacyContactsConnection *self) -{ -} - -static void -tp_tests_legacy_contacts_connection_class_init ( - TpTestsLegacyContactsConnectionClass *klass) -{ - /* Leave Contacts out of the interfaces we say are present, so clients - * won't use it */ - static const gchar *interfaces_always_present[] = { - TP_IFACE_CONNECTION_INTERFACE_ALIASING, - TP_IFACE_CONNECTION_INTERFACE_AVATARS, - TP_IFACE_CONNECTION_INTERFACE_PRESENCE, - TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE, - TP_IFACE_CONNECTION_INTERFACE_LOCATION, - TP_IFACE_CONNECTION_INTERFACE_REQUESTS, - NULL }; - TpBaseConnectionClass *base_class = - (TpBaseConnectionClass *) klass; - GObjectClass *object_class = (GObjectClass *) klass; - - object_class->get_property = legacy_contacts_connection_get_property; - - base_class->interfaces_always_present = interfaces_always_present; - - g_object_class_override_property (object_class, - LEGACY_PROP_HAS_IMMORTAL_HANDLES, "has-immortal-handles"); -} - -/* =============== No Requests and no ContactCapabilities ================= */ - -G_DEFINE_TYPE (TpTestsNoRequestsConnection, tp_tests_no_requests_connection, - TP_TESTS_TYPE_CONTACTS_CONNECTION); - -static void -tp_tests_no_requests_connection_init (TpTestsNoRequestsConnection *self) -{ -} - -static void -tp_tests_no_requests_connection_class_init ( - TpTestsNoRequestsConnectionClass *klass) -{ - static const gchar *interfaces_always_present[] = { - TP_IFACE_CONNECTION_INTERFACE_ALIASING, - TP_IFACE_CONNECTION_INTERFACE_AVATARS, - TP_IFACE_CONNECTION_INTERFACE_CONTACTS, - TP_IFACE_CONNECTION_INTERFACE_PRESENCE, - TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE, - TP_IFACE_CONNECTION_INTERFACE_LOCATION, - NULL }; - TpBaseConnectionClass *base_class = - (TpBaseConnectionClass *) klass; - - base_class->interfaces_always_present = interfaces_always_present; - base_class->create_channel_managers = NULL; -} diff --git a/tests/lib/telepathy/contactlist/contacts-conn.h b/tests/lib/telepathy/contactlist/contacts-conn.h index 64056e03..679b0eb6 100644 --- a/tests/lib/telepathy/contactlist/contacts-conn.h +++ b/tests/lib/telepathy/contactlist/contacts-conn.h @@ -13,9 +13,7 @@ #define __TP_TESTS_CONTACTS_CONN_H__ #include <glib-object.h> -#include <telepathy-glib/base-connection.h> -#include <telepathy-glib/contacts-mixin.h> -#include <telepathy-glib/presence-mixin.h> +#include <telepathy-glib/telepathy-glib.h> #include "simple-conn.h" #include "contact-list-manager.h" @@ -113,78 +111,6 @@ void tp_tests_contacts_connection_set_default_contact_info ( TpTestsContactsConnection *self, GPtrArray *info); -/* Legacy version (no Contacts interface, and no immortal handles) */ - -typedef struct _TpTestsLegacyContactsConnection TpTestsLegacyContactsConnection; -typedef struct _TpTestsLegacyContactsConnectionClass TpTestsLegacyContactsConnectionClass; -typedef struct _TpTestsLegacyContactsConnectionPrivate - TpTestsLegacyContactsConnectionPrivate; - -struct _TpTestsLegacyContactsConnectionClass { - TpTestsContactsConnectionClass parent_class; -}; - -struct _TpTestsLegacyContactsConnection { - TpTestsContactsConnection parent; - - TpTestsLegacyContactsConnectionPrivate *priv; -}; - -GType tp_tests_legacy_contacts_connection_get_type (void); - -/* TYPE MACROS */ -#define TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION \ - (tp_tests_legacy_contacts_connection_get_type ()) -#define LEGACY_TP_TESTS_CONTACTS_CONNECTION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION, \ - TpTestsLegacyContactsConnection)) -#define LEGACY_TP_TESTS_CONTACTS_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION, \ - TpTestsLegacyContactsConnectionClass)) -#define TP_TESTS_LEGACY_CONTACTS_IS_CONNECTION(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION)) -#define TP_TESTS_LEGACY_CONTACTS_IS_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION)) -#define LEGACY_TP_TESTS_CONTACTS_CONNECTION_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_LEGACY_CONTACTS_CONNECTION, \ - TpTestsLegacyContactsConnectionClass)) - -/* No Requests version */ - -typedef struct _TpTestsNoRequestsConnection TpTestsNoRequestsConnection; -typedef struct _TpTestsNoRequestsConnectionClass TpTestsNoRequestsConnectionClass; -typedef struct _TpTestsNoRequestsConnectionPrivate - TpTestsNoRequestsConnectionPrivate; - -struct _TpTestsNoRequestsConnectionClass { - TpTestsContactsConnectionClass parent_class; -}; - -struct _TpTestsNoRequestsConnection { - TpTestsContactsConnection parent; - - TpTestsNoRequestsConnectionPrivate *priv; -}; - -GType tp_tests_no_requests_connection_get_type (void); - -/* TYPE MACROS */ -#define TP_TESTS_TYPE_NO_REQUESTS_CONNECTION \ - (tp_tests_no_requests_connection_get_type ()) -#define TP_TESTS_NO_REQUESTS_CONNECTION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION, \ - TpTestsNoRequestsConnection)) -#define TP_TESTS_NO_REQUESTS_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION, \ - TpTestsNoRequestsConnectionClass)) -#define TP_TESTS_NO_REQUESTS_IS_CONNECTION(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION)) -#define TP_TESTS_NO_REQUESTS_IS_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION)) -#define TP_TESTS_NO_REQUESTS_CONNECTION_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_NO_REQUESTS_CONNECTION, \ - TpTestsNoRequestsConnectionClass)) - G_END_DECLS #endif /* ifndef __TP_TESTS_CONTACTS_CONN_H__ */ diff --git a/tests/lib/telepathy/contactlist/dbus-tube-chan.c b/tests/lib/telepathy/contactlist/dbus-tube-chan.c new file mode 100644 index 00000000..28e34b5c --- /dev/null +++ b/tests/lib/telepathy/contactlist/dbus-tube-chan.c @@ -0,0 +1,455 @@ +/* + * dbus-tube-chan.c - Simple dbus tube channel + * + * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "dbus-tube-chan.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> +#include <glib/gstdio.h> + +#if defined(G_OS_UNIX) +# define LISTEN_ADDRESS "unix:tmpdir=/tmp" +#else +# define LISTEN_ADDRESS "tcp:host=127.0.0.1" +#endif + +enum +{ + PROP_SERVICE_NAME = 1, + PROP_DBUS_NAMES, + PROP_SUPPORTED_ACCESS_CONTROLS, + PROP_PARAMETERS, + PROP_STATE, +}; + +enum +{ + SIG_NEW_CONNECTION, + LAST_SIGNAL +}; + +static guint _signals[LAST_SIGNAL] = { 0, }; + +struct _TpTestsDBusTubeChannelPrivate { + /* Controls whether the channel should become open before returning from + * Open/Accept, after returning, or never. + */ + TpTestsDBusTubeChannelOpenMode open_mode; + TpTubeChannelState state; + + /* TpHandle -> gchar * */ + GHashTable *dbus_names; + + GDBusServer *dbus_server; +}; + +static void +tp_tests_dbus_tube_channel_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + TpTestsDBusTubeChannel *self = (TpTestsDBusTubeChannel *) object; + + switch (property_id) + { + case PROP_SERVICE_NAME: + g_value_set_string (value, "com.test.Test"); + break; + + case PROP_DBUS_NAMES: + g_value_set_boxed (value, self->priv->dbus_names); + break; + + case PROP_SUPPORTED_ACCESS_CONTROLS: + { + GArray *array; + TpSocketAccessControl a; + + array = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); + + a = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; + g_array_append_val (array, a); + + g_value_set_boxed (value, array); + + g_array_unref (array); + } + break; + + case PROP_PARAMETERS: + g_value_take_boxed (value, tp_asv_new ( + "badger", G_TYPE_UINT, 42, + NULL)); + break; + + case PROP_STATE: + g_value_set_uint (value, self->priv->state); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void dbus_tube_iface_init (gpointer iface, gpointer data); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (TpTestsDBusTubeChannel, + tp_tests_dbus_tube_channel, + TP_TYPE_BASE_CHANNEL, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_DBUS_TUBE, + dbus_tube_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_TUBE, + NULL); + ) + +/* type definition stuff */ + +static GPtrArray * +tp_tests_dbus_tube_channel_get_interfaces (TpBaseChannel *self) +{ + GPtrArray *interfaces; + + interfaces = TP_BASE_CHANNEL_CLASS ( + tp_tests_dbus_tube_channel_parent_class)->get_interfaces (self); + + g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_TUBE); + return interfaces; +}; + +static void +tp_tests_dbus_tube_channel_init (TpTestsDBusTubeChannel *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), + TP_TESTS_TYPE_DBUS_TUBE_CHANNEL, TpTestsDBusTubeChannelPrivate); + + self->priv->open_mode = TP_TESTS_DBUS_TUBE_CHANNEL_OPEN_FIRST; + self->priv->dbus_names = g_hash_table_new_full (g_direct_hash, + g_direct_equal, NULL, g_free); +} + +static GObject * +constructor (GType type, + guint n_props, + GObjectConstructParam *props) +{ + GObject *object = + G_OBJECT_CLASS (tp_tests_dbus_tube_channel_parent_class)->constructor ( + type, n_props, props); + TpTestsDBusTubeChannel *self = TP_TESTS_DBUS_TUBE_CHANNEL (object); + + if (tp_base_channel_is_requested (TP_BASE_CHANNEL (self))) + self->priv->state = TP_TUBE_CHANNEL_STATE_NOT_OFFERED; + else + self->priv->state = TP_TUBE_CHANNEL_STATE_LOCAL_PENDING; + + tp_base_channel_register (TP_BASE_CHANNEL (self)); + + return object; +} + +static void +dispose (GObject *object) +{ + TpTestsDBusTubeChannel *self = (TpTestsDBusTubeChannel *) object; + + tp_clear_pointer (&self->priv->dbus_names, g_hash_table_unref); + + if (self->priv->dbus_server != NULL) + { + /* FIXME: this is pretty stupid but apparently unless you start and then + * stop the server before freeing it, it doesn't stop listening. Calling + * _start() twice is a no-op. + * + * https://bugzilla.gnome.org/show_bug.cgi?id=673372 + */ + g_dbus_server_start (self->priv->dbus_server); + + g_dbus_server_stop (self->priv->dbus_server); + g_clear_object (&self->priv->dbus_server); + } + + ((GObjectClass *) tp_tests_dbus_tube_channel_parent_class)->dispose ( + object); +} + +static void +channel_close (TpBaseChannel *channel) +{ + tp_base_channel_destroyed (channel); +} + +static void +fill_immutable_properties (TpBaseChannel *chan, + GHashTable *properties) +{ + TpBaseChannelClass *klass = TP_BASE_CHANNEL_CLASS ( + tp_tests_dbus_tube_channel_parent_class); + + klass->fill_immutable_properties (chan, properties); + + tp_dbus_properties_mixin_fill_properties_hash ( + G_OBJECT (chan), properties, + TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "ServiceName", + TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "SupportedAccessControls", + NULL); + + if (!tp_base_channel_is_requested (chan)) + { + /* Parameters is immutable only for incoming tubes */ + tp_dbus_properties_mixin_fill_properties_hash ( + G_OBJECT (chan), properties, + TP_IFACE_CHANNEL_INTERFACE_TUBE, "Parameters", + NULL); + } +} + +static void +tp_tests_dbus_tube_channel_class_init (TpTestsDBusTubeChannelClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + GParamSpec *param_spec; + static TpDBusPropertiesMixinPropImpl dbus_tube_props[] = { + { "ServiceName", "service-name", NULL, }, + { "DBusNames", "dbus-names", NULL, }, + { "SupportedAccessControls", "supported-access-controls", NULL, }, + { NULL } + }; + static TpDBusPropertiesMixinPropImpl tube_props[] = { + { "Parameters", "parameters", NULL, }, + { "State", "state", NULL, }, + { NULL } + }; + + object_class->constructor = constructor; + object_class->get_property = tp_tests_dbus_tube_channel_get_property; + object_class->dispose = dispose; + + base_class->channel_type = TP_IFACE_CHANNEL_TYPE_DBUS_TUBE; + base_class->get_interfaces = tp_tests_dbus_tube_channel_get_interfaces; + base_class->close = channel_close; + base_class->fill_immutable_properties = fill_immutable_properties; + + /* base_class->target_handle_type is defined in subclasses */ + + param_spec = g_param_spec_string ("service-name", "Service Name", + "the service name associated with this tube object.", + "", + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_SERVICE_NAME, param_spec); + + param_spec = g_param_spec_boxed ("dbus-names", "DBus Names", + "DBusTube.DBusNames", + TP_HASH_TYPE_DBUS_TUBE_PARTICIPANTS, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_DBUS_NAMES, param_spec); + + param_spec = g_param_spec_boxed ("supported-access-controls", + "Supported access-controls", + "GArray containing supported access controls.", + DBUS_TYPE_G_UINT_ARRAY, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_SUPPORTED_ACCESS_CONTROLS, param_spec); + + param_spec = g_param_spec_boxed ( + "parameters", "Parameters", + "parameters of the tube", + TP_HASH_TYPE_STRING_VARIANT_MAP, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_PARAMETERS, + param_spec); + + param_spec = g_param_spec_uint ( + "state", "TpTubeState", + "state of the tube", + 0, TP_NUM_TUBE_CHANNEL_STATES - 1, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_STATE, + param_spec); + + _signals[SIG_NEW_CONNECTION] = g_signal_new ("new-connection", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_true_handled, NULL, + NULL, + G_TYPE_BOOLEAN, + 1, G_TYPE_DBUS_CONNECTION); + + tp_dbus_properties_mixin_implement_interface (object_class, + TP_IFACE_QUARK_CHANNEL_TYPE_DBUS_TUBE, + tp_dbus_properties_mixin_getter_gobject_properties, NULL, + dbus_tube_props); + + tp_dbus_properties_mixin_implement_interface (object_class, + TP_IFACE_QUARK_CHANNEL_INTERFACE_TUBE, + tp_dbus_properties_mixin_getter_gobject_properties, NULL, + tube_props); + + g_type_class_add_private (object_class, + sizeof (TpTestsDBusTubeChannelPrivate)); +} + +static void +change_state (TpTestsDBusTubeChannel *self, + TpTubeChannelState state) +{ + self->priv->state = state; + + tp_svc_channel_interface_tube_emit_tube_channel_state_changed (self, state); +} + +static gboolean +dbus_new_connection_cb (GDBusServer *server, + GDBusConnection *connection, + gpointer user_data) +{ + TpTestsDBusTubeChannel *self = user_data; + gboolean ret = FALSE; + + g_signal_emit (self, _signals[SIG_NEW_CONNECTION], 0, connection, &ret); + return ret; +} + +static void +open_tube (TpTestsDBusTubeChannel *self) +{ + GError *error = NULL; + gchar *guid; + + guid = g_dbus_generate_guid (); + + self->priv->dbus_server = g_dbus_server_new_sync (LISTEN_ADDRESS, + G_DBUS_SERVER_FLAGS_NONE, guid, NULL, NULL, &error); + g_assert_no_error (error); + + g_free (guid); + + g_signal_connect (self->priv->dbus_server, "new-connection", + G_CALLBACK (dbus_new_connection_cb), self); +} + +static void +really_open_tube (TpTestsDBusTubeChannel *self) +{ + g_dbus_server_start (self->priv->dbus_server); + + change_state (self, TP_TUBE_CHANNEL_STATE_OPEN); +} + +static void +dbus_tube_offer (TpSvcChannelTypeDBusTube *chan, + GHashTable *parameters, + guint access_control, + DBusGMethodInvocation *context) +{ + TpTestsDBusTubeChannel *self = (TpTestsDBusTubeChannel *) chan; + + open_tube (self); + + if (self->priv->open_mode == TP_TESTS_DBUS_TUBE_CHANNEL_OPEN_FIRST) + really_open_tube (self); + + tp_svc_channel_type_dbus_tube_return_from_offer (context, + g_dbus_server_get_client_address (self->priv->dbus_server)); + + if (self->priv->open_mode == TP_TESTS_DBUS_TUBE_CHANNEL_OPEN_SECOND) + really_open_tube (self); + else if (self->priv->open_mode == TP_TESTS_DBUS_TUBE_CHANNEL_NEVER_OPEN) + tp_base_channel_close (TP_BASE_CHANNEL (self)); +} + +static void +dbus_tube_accept (TpSvcChannelTypeDBusTube *chan, + guint access_control, + DBusGMethodInvocation *context) +{ + TpTestsDBusTubeChannel *self = (TpTestsDBusTubeChannel *) chan; + + open_tube (self); + + if (self->priv->open_mode == TP_TESTS_DBUS_TUBE_CHANNEL_OPEN_FIRST) + really_open_tube (self); + + tp_svc_channel_type_dbus_tube_return_from_accept (context, + g_dbus_server_get_client_address (self->priv->dbus_server)); + + if (self->priv->open_mode == TP_TESTS_DBUS_TUBE_CHANNEL_OPEN_SECOND) + really_open_tube (self); + else if (self->priv->open_mode == TP_TESTS_DBUS_TUBE_CHANNEL_NEVER_OPEN) + tp_base_channel_close (TP_BASE_CHANNEL (self)); +} + +void +tp_tests_dbus_tube_channel_set_open_mode ( + TpTestsDBusTubeChannel *self, + TpTestsDBusTubeChannelOpenMode open_mode) +{ + self->priv->open_mode = open_mode; +} + +static void +dbus_tube_iface_init (gpointer iface, + gpointer data) +{ + TpSvcChannelTypeDBusTubeClass *klass = iface; + +#define IMPLEMENT(x) tp_svc_channel_type_dbus_tube_implement_##x (klass, dbus_tube_##x) + IMPLEMENT (offer); + IMPLEMENT (accept); +#undef IMPLEMENT +} + +/* Contact DBus Tube */ + +G_DEFINE_TYPE (TpTestsContactDBusTubeChannel, + tp_tests_contact_dbus_tube_channel, + TP_TESTS_TYPE_DBUS_TUBE_CHANNEL) + +static void +tp_tests_contact_dbus_tube_channel_init ( + TpTestsContactDBusTubeChannel *self) +{ +} + +static void +tp_tests_contact_dbus_tube_channel_class_init ( + TpTestsContactDBusTubeChannelClass *klass) +{ + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + + base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; +} + +/* Room DBus Tube */ + +G_DEFINE_TYPE (TpTestsRoomDBusTubeChannel, + tp_tests_room_dbus_tube_channel, + TP_TESTS_TYPE_DBUS_TUBE_CHANNEL) + +static void +tp_tests_room_dbus_tube_channel_init ( + TpTestsRoomDBusTubeChannel *self) +{ +} + +static void +tp_tests_room_dbus_tube_channel_class_init ( + TpTestsRoomDBusTubeChannelClass *klass) +{ + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + + base_class->target_handle_type = TP_HANDLE_TYPE_ROOM; +} diff --git a/tests/lib/telepathy/contactlist/dbus-tube-chan.h b/tests/lib/telepathy/contactlist/dbus-tube-chan.h new file mode 100644 index 00000000..71800970 --- /dev/null +++ b/tests/lib/telepathy/contactlist/dbus-tube-chan.h @@ -0,0 +1,127 @@ +/* + * dbus-tube-chan.h - Simple dbus tube channel + * + * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_DBUS_TUBE_CHAN_H__ +#define __TP_DBUS_TUBE_CHAN_H__ + +#include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + +G_BEGIN_DECLS + +/* Base Class */ +typedef struct _TpTestsDBusTubeChannel TpTestsDBusTubeChannel; +typedef struct _TpTestsDBusTubeChannelClass TpTestsDBusTubeChannelClass; +typedef struct _TpTestsDBusTubeChannelPrivate TpTestsDBusTubeChannelPrivate; + +GType tp_tests_dbus_tube_channel_get_type (void); + +#define TP_TESTS_TYPE_DBUS_TUBE_CHANNEL \ + (tp_tests_dbus_tube_channel_get_type ()) +#define TP_TESTS_DBUS_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_DBUS_TUBE_CHANNEL, \ + TpTestsDBusTubeChannel)) +#define TP_TESTS_DBUS_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_DBUS_TUBE_CHANNEL, \ + TpTestsDBusTubeChannelClass)) +#define TP_TESTS_IS_DBUS_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_DBUS_TUBE_CHANNEL)) +#define TP_TESTS_IS_DBUS_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_DBUS_TUBE_CHANNEL)) +#define TP_TESTS_DBUS_TUBE_CHANNEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_DBUS_TUBE_CHANNEL, \ + TpTestsDBusTubeChannelClass)) + +struct _TpTestsDBusTubeChannelClass { + TpBaseChannelClass parent_class; + TpDBusPropertiesMixinClass dbus_properties_class; +}; + +struct _TpTestsDBusTubeChannel { + TpBaseChannel parent; + + TpTestsDBusTubeChannelPrivate *priv; +}; + +typedef enum { + TP_TESTS_DBUS_TUBE_CHANNEL_OPEN_FIRST, + TP_TESTS_DBUS_TUBE_CHANNEL_OPEN_SECOND, + TP_TESTS_DBUS_TUBE_CHANNEL_NEVER_OPEN +} TpTestsDBusTubeChannelOpenMode; + +void tp_tests_dbus_tube_channel_set_open_mode ( + TpTestsDBusTubeChannel *self, + TpTestsDBusTubeChannelOpenMode open_mode); + +/* Contact DBus Tube */ + +typedef struct _TpTestsContactDBusTubeChannel TpTestsContactDBusTubeChannel; +typedef struct _TpTestsContactDBusTubeChannelClass TpTestsContactDBusTubeChannelClass; + +GType tp_tests_contact_dbus_tube_channel_get_type (void); + +#define TP_TESTS_TYPE_CONTACT_DBUS_TUBE_CHANNEL \ + (tp_tests_contact_dbus_tube_channel_get_type ()) +#define TP_TESTS_CONTACT_DBUS_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_CONTACT_DBUS_TUBE_CHANNEL, \ + TpTestsContactDBusTubeChannel)) +#define TP_TESTS_CONTACT_DBUS_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_CONTACT_DBUS_TUBE_CHANNEL, \ + TpTestsContactDBusTubeChannelClass)) +#define TP_TESTS_IS_CONTACT_DBUS_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_CONTACT_DBUS_TUBE_CHANNEL)) +#define TP_TESTS_IS_CONTACT_DBUS_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_CONTACT_DBUS_TUBE_CHANNEL)) +#define TP_TESTS_CONTACT_DBUS_TUBE_CHANNEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_CONTACT_DBUS_TUBE_CHANNEL, \ + TpTestsContactDBusTubeChannelClass)) + +struct _TpTestsContactDBusTubeChannelClass { + TpTestsDBusTubeChannelClass parent_class; +}; + +struct _TpTestsContactDBusTubeChannel { + TpTestsDBusTubeChannel parent; +}; + +/* Room DBus Tube */ + +typedef struct _TpTestsRoomDBusTubeChannel TpTestsRoomDBusTubeChannel; +typedef struct _TpTestsRoomDBusTubeChannelClass TpTestsRoomDBusTubeChannelClass; + +GType tp_tests_room_dbus_tube_channel_get_type (void); + +#define TP_TESTS_TYPE_ROOM_DBUS_TUBE_CHANNEL \ + (tp_tests_room_dbus_tube_channel_get_type ()) +#define TP_TESTS_ROOM_DBUS_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_ROOM_DBUS_TUBE_CHANNEL, \ + TpTestsRoomDBusTubeChannel)) +#define TP_TESTS_ROOM_DBUS_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_ROOM_DBUS_TUBE_CHANNEL, \ + TpTestsRoomDBusTubeChannelClass)) +#define TP_TESTS_IS_ROOM_DBUS_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_ROOM_DBUS_TUBE_CHANNEL)) +#define TP_TESTS_IS_ROOM_DBUS_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_ROOM_DBUS_TUBE_CHANNEL)) +#define TP_TESTS_ROOM_DBUS_TUBE_CHANNEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_ROOM_DBUS_TUBE_CHANNEL, \ + TpTestsRoomDBusTubeChannelClass)) + +struct _TpTestsRoomDBusTubeChannelClass { + TpTestsDBusTubeChannelClass parent_class; +}; + +struct _TpTestsRoomDBusTubeChannel { + TpTestsDBusTubeChannel parent; +}; + +G_END_DECLS + +#endif /* #ifndef __TP_DBUS_TUBE_CHAN_H__ */ diff --git a/tests/lib/telepathy/contactlist/echo-chan.c b/tests/lib/telepathy/contactlist/echo-chan.c new file mode 100644 index 00000000..868fbcf4 --- /dev/null +++ b/tests/lib/telepathy/contactlist/echo-chan.c @@ -0,0 +1,223 @@ +/* + * chan.c - an example text channel talking to a particular + * contact. Similar code is used for 1-1 IM channels in many protocols + * (IRC private messages ("/query"), XMPP IM etc.) + * + * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2007 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "echo-chan.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +static void destroyable_iface_init (gpointer iface, gpointer data); + +G_DEFINE_TYPE_WITH_CODE (TpTestsEchoChannel, + tp_tests_echo_channel, + TP_TYPE_BASE_CHANNEL, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, + tp_message_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DESTROYABLE, + destroyable_iface_init); + ) + +/* type definition stuff */ + +static GPtrArray * +tp_tests_echo_channel_get_interfaces (TpBaseChannel *self) +{ + GPtrArray *interfaces; + + interfaces = TP_BASE_CHANNEL_CLASS (tp_tests_echo_channel_parent_class)-> + get_interfaces (self); + + g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_DESTROYABLE); + return interfaces; +}; + +static void +tp_tests_echo_channel_init (TpTestsEchoChannel *self) +{ +} + +static void text_send (GObject *object, TpMessage *message, + TpMessageSendingFlags flags); + +static void +constructed (GObject *object) +{ + TpTestsEchoChannel *self = TP_TESTS_ECHO_CHANNEL (object); + TpBaseConnection *conn = tp_base_channel_get_connection (TP_BASE_CHANNEL (self)); + const TpChannelTextMessageType types[] = { + TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, + TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION, + TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, + }; + const gchar * supported_content_types[] = { + "text/plain", + NULL + }; + g_assert (conn != NULL); + + G_OBJECT_CLASS (tp_tests_echo_channel_parent_class)->constructed (object); + + tp_base_channel_register (TP_BASE_CHANNEL (self)); + + tp_message_mixin_init (object, + G_STRUCT_OFFSET (TpTestsEchoChannel, message), + conn); + tp_message_mixin_implement_sending (object, + text_send, G_N_ELEMENTS (types), types, 0, 0, + supported_content_types); +} + +static void +finalize (GObject *object) +{ + tp_message_mixin_finalize (object); + + ((GObjectClass *) tp_tests_echo_channel_parent_class)->finalize (object); +} + +static void +tp_tests_echo_channel_close (TpTestsEchoChannel *self) +{ + GObject *object = (GObject *) self; + gboolean closed = tp_base_channel_is_destroyed (TP_BASE_CHANNEL (self)); + + if (!closed) + { + TpHandle first_sender; + + /* The manager wants to be able to respawn the channel if it has pending + * messages. When respawned, the channel must have the initiator set + * to the contact who sent us those messages (if it isn't already), + * and the messages must be marked as having been rescued so they + * don't get logged twice. */ + if (tp_message_mixin_has_pending_messages (object, &first_sender)) + { + tp_base_channel_reopened (TP_BASE_CHANNEL (self), first_sender); + tp_message_mixin_set_rescued (object); + } + else + { + tp_base_channel_destroyed (TP_BASE_CHANNEL (self)); + } + } +} + +static void +channel_close (TpBaseChannel *channel) +{ + TpTestsEchoChannel *self = TP_TESTS_ECHO_CHANNEL (channel); + + tp_tests_echo_channel_close (self); +} + +static void +tp_tests_echo_channel_class_init (TpTestsEchoChannelClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + + object_class->constructed = constructed; + object_class->finalize = finalize; + + base_class->channel_type = TP_IFACE_CHANNEL_TYPE_TEXT; + base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; + base_class->get_interfaces = tp_tests_echo_channel_get_interfaces; + base_class->close = channel_close; + + tp_message_mixin_init_dbus_properties (object_class); +} + + +static void +text_send (GObject *object, + TpMessage *message, + TpMessageSendingFlags flags) +{ + TpTestsEchoChannel *self = TP_TESTS_ECHO_CHANNEL (object); + TpChannelTextMessageType type = tp_message_get_message_type (message); + TpChannelTextMessageType echo_type = type; + TpHandle target = tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self)); + gchar *echo; + gint64 now = time (NULL); + const GHashTable *part; + const gchar *text; + TpMessage *msg; + + /* Pretend that the remote contact has replied. Normally, you'd + * call tp_text_mixin_receive or tp_text_mixin_receive_with_flags + * in response to network events */ + + part = tp_message_peek (message, 1); + text = tp_asv_get_string (part, "content"); + + switch (type) + { + case TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL: + echo = g_strdup_printf ("You said: %s", text); + break; + case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION: + echo = g_strdup_printf ("notices that the user %s", text); + break; + case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE: + echo = g_strdup_printf ("You sent a notice: %s", text); + break; + default: + echo = g_strdup_printf ("You sent some weird message type, %u: \"%s\"", + type, text); + echo_type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; + } + + tp_message_mixin_sent (object, message, 0, "", NULL); + + msg = tp_cm_message_new ( + tp_base_channel_get_connection (TP_BASE_CHANNEL (self)), + 2); + + tp_cm_message_set_sender (msg, target); + tp_message_set_uint32 (msg, 0, "message-type", echo_type); + tp_message_set_int64 (msg, 0, "message-sent", now); + tp_message_set_int64 (msg, 0, "message-received", now); + + tp_message_set_string (msg, 1, "content-type", "text/plain"); + tp_message_set_string (msg, 1, "content", echo); + + tp_message_mixin_take_received (object, msg); + + g_free (echo); +} + +static void +destroyable_destroy (TpSvcChannelInterfaceDestroyable *iface, + DBusGMethodInvocation *context) +{ + TpTestsEchoChannel *self = TP_TESTS_ECHO_CHANNEL (iface); + + tp_message_mixin_clear ((GObject *) self); + tp_base_channel_destroyed (TP_BASE_CHANNEL (self)); + + tp_svc_channel_interface_destroyable_return_from_destroy (context); +} + +static void +destroyable_iface_init (gpointer iface, + gpointer data) +{ + TpSvcChannelInterfaceDestroyableClass *klass = iface; + +#define IMPLEMENT(x) \ + tp_svc_channel_interface_destroyable_implement_##x (klass, destroyable_##x) + IMPLEMENT (destroy); +#undef IMPLEMENT +} diff --git a/tests/lib/telepathy/contactlist/echo-chan.h b/tests/lib/telepathy/contactlist/echo-chan.h new file mode 100644 index 00000000..5fbe6ee5 --- /dev/null +++ b/tests/lib/telepathy/contactlist/echo-chan.h @@ -0,0 +1,56 @@ +/* + * chan.h - header for an example channel + * + * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2007 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_CHAN_H__ +#define __TP_TESTS_CHAN_H__ + +#include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + +G_BEGIN_DECLS + +typedef struct _TpTestsEchoChannel TpTestsEchoChannel; +typedef struct _TpTestsEchoChannelClass TpTestsEchoChannelClass; +typedef struct _TpTestsEchoChannelPrivate TpTestsEchoChannelPrivate; + +GType tp_tests_echo_channel_get_type (void); + +#define TP_TESTS_TYPE_ECHO_CHANNEL \ + (tp_tests_echo_channel_get_type ()) +#define TP_TESTS_ECHO_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_ECHO_CHANNEL, \ + TpTestsEchoChannel)) +#define TP_TESTS_ECHO_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_ECHO_CHANNEL, \ + TpTestsEchoChannelClass)) +#define TP_TESTS_IS_ECHO_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_ECHO_CHANNEL)) +#define TP_TESTS_IS_ECHO_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_ECHO_CHANNEL)) +#define TP_TESTS_ECHO_CHANNEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_ECHO_CHANNEL, \ + TpTestsEchoChannelClass)) + +struct _TpTestsEchoChannelClass { + TpBaseChannelClass parent_class; + TpDBusPropertiesMixinClass dbus_properties_class; +}; + +struct _TpTestsEchoChannel { + TpBaseChannel parent; + TpMessageMixin message; + + TpTestsEchoChannelPrivate *priv; +}; + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_CHAN_H__ */ diff --git a/tests/lib/telepathy/contactlist/echo-conn.c b/tests/lib/telepathy/contactlist/echo-conn.c new file mode 100644 index 00000000..e985ec67 --- /dev/null +++ b/tests/lib/telepathy/contactlist/echo-conn.c @@ -0,0 +1,165 @@ +/* + * conn.c - an example connection + * + * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2007 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "echo-conn.h" + +#include <dbus/dbus-glib.h> + +#include <telepathy-glib/telepathy-glib.h> + +#include "echo-im-manager.h" +#include "simple-channel-manager.h" + +G_DEFINE_TYPE (TpTestsEchoConnection, + tp_tests_echo_connection, + TP_TESTS_TYPE_CONTACTS_CONNECTION) + +/* type definition stuff */ + +enum +{ + PROP_CHANNEL_MANAGER = 1, + N_PROPS +}; + +struct _TpTestsEchoConnectionPrivate +{ + TpTestsSimpleChannelManager *channel_manager; +}; + + +static void +tp_tests_echo_connection_init (TpTestsEchoConnection *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_ECHO_CONNECTION, + TpTestsEchoConnectionPrivate); +} + +/* Returns the same id given in but in lowercase. If '#' is present, + * the normalized contact will be the lhs of it. For example: + * + * LOL -> lol + * Lol#foo -> lol + */ +static gchar * +tp_tests_echo_normalize_contact (TpHandleRepoIface *repo, + const gchar *id, + gpointer context, + GError **error) +{ + gchar *hash; + + if (id[0] == '\0') + { + g_set_error (error, TP_ERROR, TP_ERROR_INVALID_HANDLE, + "ID must not be empty"); + return NULL; + } + + hash = g_utf8_strchr (id, -1, '#'); + + return g_utf8_strdown (id, hash != NULL ? (hash - id) : -1); +} + +static void +create_handle_repos (TpBaseConnection *conn, + TpHandleRepoIface *repos[TP_NUM_HANDLE_TYPES]) +{ + ((TpBaseConnectionClass *) + tp_tests_echo_connection_parent_class)->create_handle_repos (conn, repos); + + /* Replace the contacts handle repo with our own, for special normalization */ + g_assert (repos[TP_HANDLE_TYPE_CONTACT] != NULL); + g_object_unref (repos[TP_HANDLE_TYPE_CONTACT]); + repos[TP_HANDLE_TYPE_CONTACT] = tp_dynamic_handle_repo_new + (TP_HANDLE_TYPE_CONTACT, tp_tests_echo_normalize_contact, NULL); +} + +static GPtrArray * +create_channel_managers (TpBaseConnection *conn) +{ + TpTestsEchoConnection *self = TP_TESTS_ECHO_CONNECTION (conn); + GPtrArray *ret; + + ret = ((TpBaseConnectionClass *) + tp_tests_echo_connection_parent_class)->create_channel_managers (conn); + + if (self->priv->channel_manager == NULL) + { + self->priv->channel_manager = g_object_new (TP_TESTS_TYPE_ECHO_IM_MANAGER, + "connection", conn, + NULL); + } + + /* tp-glib will free this for us so we don't need to worry about + doing it ourselves. */ + g_ptr_array_add (ret, self->priv->channel_manager); + + return ret; +} + +static void +get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *spec) +{ + TpTestsEchoConnection *self = TP_TESTS_ECHO_CONNECTION (object); + + switch (property_id) { + case PROP_CHANNEL_MANAGER: + g_assert (self->priv->channel_manager == NULL); /* construct-only */ + g_value_set_object (value, self->priv->channel_manager); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); + } +} + +static void +set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *spec) +{ + TpTestsEchoConnection *self = TP_TESTS_ECHO_CONNECTION (object); + + switch (property_id) { + case PROP_CHANNEL_MANAGER: + self->priv->channel_manager = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); + } +} + +static void +tp_tests_echo_connection_class_init (TpTestsEchoConnectionClass *klass) +{ + TpBaseConnectionClass *base_class = + (TpBaseConnectionClass *) klass; + GObjectClass *object_class = (GObjectClass *) klass; + GParamSpec *param_spec; + + object_class->get_property = get_property; + object_class->set_property = set_property; + g_type_class_add_private (klass, sizeof (TpTestsEchoConnectionPrivate)); + + base_class->create_handle_repos = create_handle_repos; + base_class->create_channel_managers = create_channel_managers; + + param_spec = g_param_spec_object ("channel-manager", "Channel manager", + "The channel manager", TP_TESTS_TYPE_SIMPLE_CHANNEL_MANAGER, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_CHANNEL_MANAGER, param_spec); +} diff --git a/tests/lib/telepathy/contactlist/echo-conn.h b/tests/lib/telepathy/contactlist/echo-conn.h new file mode 100644 index 00000000..ffc8f4d9 --- /dev/null +++ b/tests/lib/telepathy/contactlist/echo-conn.h @@ -0,0 +1,56 @@ +/* + * conn.h - header for an example connection + * + * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2007 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_ECHO_CONN_H__ +#define __TP_TESTS_ECHO_CONN_H__ + +#include <glib-object.h> + +#include "contacts-conn.h" + +G_BEGIN_DECLS + +typedef struct _TpTestsEchoConnection TpTestsEchoConnection; +typedef struct _TpTestsEchoConnectionClass TpTestsEchoConnectionClass; +typedef struct _TpTestsEchoConnectionPrivate TpTestsEchoConnectionPrivate; + +struct _TpTestsEchoConnectionClass { + TpTestsContactsConnectionClass parent_class; +}; + +struct _TpTestsEchoConnection { + TpTestsContactsConnection parent; + + TpTestsEchoConnectionPrivate *priv; +}; + +GType tp_tests_echo_connection_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_ECHO_CONNECTION \ + (tp_tests_echo_connection_get_type ()) +#define TP_TESTS_ECHO_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_ECHO_CONNECTION, \ + TpTestsEchoConnection)) +#define TP_TESTS_ECHO_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_ECHO_CONNECTION, \ + TpTestsEchoConnectionClass)) +#define TP_TESTS_IS_ECHO_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_ECHO_CONNECTION)) +#define TP_TESTS_IS_ECHO_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_ECHO_CONNECTION)) +#define TP_TESTS_ECHO_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_ECHO_CONNECTION, \ + TpTestsEchoConnectionClass)) + +G_END_DECLS + +#endif diff --git a/tests/lib/telepathy/contactlist/echo-im-manager.c b/tests/lib/telepathy/contactlist/echo-im-manager.c new file mode 100644 index 00000000..8c381866 --- /dev/null +++ b/tests/lib/telepathy/contactlist/echo-im-manager.c @@ -0,0 +1,382 @@ +/* + * im-manager.c - an example channel manager for channels talking to a + * particular contact. Similar code is used for 1-1 IM channels in many + * protocols (IRC private messages ("/query"), XMPP IM etc.) + * + * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2007 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "echo-im-manager.h" + +#include <dbus/dbus-glib.h> + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +#include "echo-chan.h" + +static void channel_manager_iface_init (gpointer, gpointer); + +G_DEFINE_TYPE_WITH_CODE (TpTestsEchoImManager, + tp_tests_echo_im_manager, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, + channel_manager_iface_init)) + +/* type definition stuff */ + +enum +{ + PROP_CONNECTION = 1, + N_PROPS +}; + +struct _TpTestsEchoImManagerPrivate +{ + TpBaseConnection *conn; + + /* GUINT_TO_POINTER (handle) => TpTestsEchoChannel */ + GHashTable *channels; + gulong status_changed_id; +}; + +static void +tp_tests_echo_im_manager_init (TpTestsEchoImManager *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_ECHO_IM_MANAGER, + TpTestsEchoImManagerPrivate); + + self->priv->channels = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, g_object_unref); +} + +static void tp_tests_echo_im_manager_close_all (TpTestsEchoImManager *self); + +static void +dispose (GObject *object) +{ + TpTestsEchoImManager *self = TP_TESTS_ECHO_IM_MANAGER (object); + + tp_tests_echo_im_manager_close_all (self); + g_assert (self->priv->channels == NULL); + + ((GObjectClass *) tp_tests_echo_im_manager_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + TpTestsEchoImManager *self = TP_TESTS_ECHO_IM_MANAGER (object); + + switch (property_id) + { + case PROP_CONNECTION: + g_value_set_object (value, self->priv->conn); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + TpTestsEchoImManager *self = TP_TESTS_ECHO_IM_MANAGER (object); + + switch (property_id) + { + case PROP_CONNECTION: + /* We don't ref the connection, because it owns a reference to the + * channel manager, and it guarantees that the manager's lifetime is + * less than its lifetime */ + self->priv->conn = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +status_changed_cb (TpBaseConnection *conn, + guint status, + guint reason, + TpTestsEchoImManager *self) +{ + if (status == TP_CONNECTION_STATUS_DISCONNECTED) + tp_tests_echo_im_manager_close_all (self); +} + +static void +constructed (GObject *object) +{ + TpTestsEchoImManager *self = TP_TESTS_ECHO_IM_MANAGER (object); + void (*chain_up) (GObject *) = + ((GObjectClass *) tp_tests_echo_im_manager_parent_class)->constructed; + + if (chain_up != NULL) + { + chain_up (object); + } + + self->priv->status_changed_id = g_signal_connect (self->priv->conn, + "status-changed", (GCallback) status_changed_cb, self); +} + +static void +tp_tests_echo_im_manager_class_init (TpTestsEchoImManagerClass *klass) +{ + GParamSpec *param_spec; + GObjectClass *object_class = (GObjectClass *) klass; + + object_class->constructed = constructed; + object_class->dispose = dispose; + object_class->get_property = get_property; + object_class->set_property = set_property; + + param_spec = g_param_spec_object ("connection", "Connection object", + "The connection that owns this channel manager", + TP_TYPE_BASE_CONNECTION, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); + + g_type_class_add_private (klass, sizeof (TpTestsEchoImManagerPrivate)); +} + +static void +tp_tests_echo_im_manager_close_all (TpTestsEchoImManager *self) +{ + if (self->priv->channels != NULL) + { + GHashTable *tmp = self->priv->channels; + + self->priv->channels = NULL; + g_hash_table_unref (tmp); + } + + if (self->priv->status_changed_id != 0) + { + g_signal_handler_disconnect (self->priv->conn, + self->priv->status_changed_id); + self->priv->status_changed_id = 0; + } +} + +static void +tp_tests_echo_im_manager_foreach_channel (TpChannelManager *iface, + TpExportableChannelFunc callback, + gpointer user_data) +{ + TpTestsEchoImManager *self = TP_TESTS_ECHO_IM_MANAGER (iface); + GHashTableIter iter; + gpointer handle, channel; + + g_hash_table_iter_init (&iter, self->priv->channels); + + while (g_hash_table_iter_next (&iter, &handle, &channel)) + { + callback (TP_EXPORTABLE_CHANNEL (channel), user_data); + } +} + +static void +channel_closed_cb (TpTestsEchoChannel *chan, + TpTestsEchoImManager *self) +{ + tp_channel_manager_emit_channel_closed_for_object (self, + TP_EXPORTABLE_CHANNEL (chan)); + + if (self->priv->channels != NULL) + { + TpHandle handle; + gboolean really_destroyed; + + g_object_get (chan, + "handle", &handle, + "channel-destroyed", &really_destroyed, + NULL); + + /* Re-announce the channel if it's not yet ready to go away (pending + * messages) */ + if (really_destroyed) + { + g_hash_table_remove (self->priv->channels, + GUINT_TO_POINTER (handle)); + } + else + { + tp_channel_manager_emit_new_channel (self, + TP_EXPORTABLE_CHANNEL (chan), NULL); + } + } +} + +static void +new_channel (TpTestsEchoImManager *self, + TpHandle handle, + TpHandle initiator, + gpointer request_token) +{ + TpTestsEchoChannel *chan; + gchar *object_path; + GSList *requests = NULL; + + object_path = g_strdup_printf ("%s/EchoChannel%u", + tp_base_connection_get_object_path (self->priv->conn), handle); + + chan = g_object_new (TP_TESTS_TYPE_ECHO_CHANNEL, + "connection", self->priv->conn, + "object-path", object_path, + "handle", handle, + "initiator-handle", initiator, + NULL); + + g_free (object_path); + + g_signal_connect (chan, "closed", (GCallback) channel_closed_cb, self); + + /* self->priv->channels takes ownership of 'chan' */ + g_hash_table_insert (self->priv->channels, GUINT_TO_POINTER (handle), chan); + + if (request_token != NULL) + requests = g_slist_prepend (requests, request_token); + + tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (chan), + requests); + g_slist_free (requests); +} + +static const gchar * const fixed_properties[] = { + TP_PROP_CHANNEL_CHANNEL_TYPE, + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, + NULL +}; + +static const gchar * const allowed_properties[] = { + TP_PROP_CHANNEL_TARGET_HANDLE, + TP_PROP_CHANNEL_TARGET_ID, + NULL +}; + +static void +tp_tests_echo_im_manager_foreach_channel_class (TpChannelManager *manager, + TpChannelManagerChannelClassFunc func, + gpointer user_data) +{ + GHashTable *table = tp_asv_new ( + TP_PROP_CHANNEL_CHANNEL_TYPE, + G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT, + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT, + NULL); + + + func (manager, table, allowed_properties, user_data); + + g_hash_table_unref (table); +} + +static gboolean +tp_tests_echo_im_manager_request (TpTestsEchoImManager *self, + gpointer request_token, + GHashTable *request_properties, + gboolean require_new) +{ + TpHandle handle; + TpTestsEchoChannel *chan; + GError *error = NULL; + + if (tp_strdiff (tp_asv_get_string (request_properties, + TP_PROP_CHANNEL_CHANNEL_TYPE), + TP_IFACE_CHANNEL_TYPE_TEXT)) + { + return FALSE; + } + + if (tp_asv_get_uint32 (request_properties, + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != TP_HANDLE_TYPE_CONTACT) + { + return FALSE; + } + + handle = tp_asv_get_uint32 (request_properties, + TP_PROP_CHANNEL_TARGET_HANDLE, NULL); + g_assert (handle != 0); + + if (tp_channel_manager_asv_has_unknown_properties (request_properties, + fixed_properties, allowed_properties, &error)) + { + goto error; + } + + chan = g_hash_table_lookup (self->priv->channels, GUINT_TO_POINTER (handle)); + + if (chan == NULL) + { + new_channel (self, handle, + tp_base_connection_get_self_handle (self->priv->conn), + request_token); + } + else if (require_new) + { + g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, + "An echo channel to contact #%u already exists", handle); + goto error; + } + else + { + tp_channel_manager_emit_request_already_satisfied (self, + request_token, TP_EXPORTABLE_CHANNEL (chan)); + } + + return TRUE; + +error: + tp_channel_manager_emit_request_failed (self, request_token, + error->domain, error->code, error->message); + g_error_free (error); + return TRUE; +} + +static gboolean +tp_tests_echo_im_manager_create_channel (TpChannelManager *manager, + gpointer request_token, + GHashTable *request_properties) +{ + return tp_tests_echo_im_manager_request (TP_TESTS_ECHO_IM_MANAGER (manager), + request_token, request_properties, TRUE); +} + +static gboolean +tp_tests_echo_im_manager_ensure_channel (TpChannelManager *manager, + gpointer request_token, + GHashTable *request_properties) +{ + return tp_tests_echo_im_manager_request (TP_TESTS_ECHO_IM_MANAGER (manager), + request_token, request_properties, FALSE); +} + +static void +channel_manager_iface_init (gpointer g_iface, + gpointer iface_data G_GNUC_UNUSED) +{ + TpChannelManagerIface *iface = g_iface; + + iface->foreach_channel = tp_tests_echo_im_manager_foreach_channel; + iface->foreach_channel_class = tp_tests_echo_im_manager_foreach_channel_class; + iface->create_channel = tp_tests_echo_im_manager_create_channel; + iface->ensure_channel = tp_tests_echo_im_manager_ensure_channel; + /* In this channel manager, Request has the same semantics as Ensure */ + iface->request_channel = tp_tests_echo_im_manager_ensure_channel; +} diff --git a/tests/lib/telepathy/contactlist/echo-im-manager.h b/tests/lib/telepathy/contactlist/echo-im-manager.h new file mode 100644 index 00000000..a33b83ef --- /dev/null +++ b/tests/lib/telepathy/contactlist/echo-im-manager.h @@ -0,0 +1,54 @@ +/* + * im-manager.h - header for an example channel manager + * + * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2007 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_ECHO_IM_MANAGER_H__ +#define __TP_TESTS_ECHO_IM_MANAGER_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +typedef struct _TpTestsEchoImManager TpTestsEchoImManager; +typedef struct _TpTestsEchoImManagerClass TpTestsEchoImManagerClass; +typedef struct _TpTestsEchoImManagerPrivate TpTestsEchoImManagerPrivate; + +struct _TpTestsEchoImManagerClass { + GObjectClass parent_class; +}; + +struct _TpTestsEchoImManager { + GObject parent; + + TpTestsEchoImManagerPrivate *priv; +}; + +GType tp_tests_echo_im_manager_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_ECHO_IM_MANAGER \ + (tp_tests_echo_im_manager_get_type ()) +#define TP_TESTS_ECHO_IM_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_ECHO_IM_MANAGER, \ + TpTestsEchoImManager)) +#define TP_TESTS_ECHO_IM_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_ECHO_IM_MANAGER, \ + TpTestsEchoImManagerClass)) +#define TP_TESTS_IS_ECHO_IM_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_ECHO_IM_MANAGER)) +#define TP_TESTS_IS_ECHO_IM_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_ECHO_IM_MANAGER)) +#define TP_TESTS_ECHO_IM_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_ECHO_IM_MANAGER, \ + TpTestsEchoImManagerClass)) + +G_END_DECLS + +#endif diff --git a/tests/lib/telepathy/contactlist/file-transfer-chan.c b/tests/lib/telepathy/contactlist/file-transfer-chan.c new file mode 100644 index 00000000..92520f48 --- /dev/null +++ b/tests/lib/telepathy/contactlist/file-transfer-chan.c @@ -0,0 +1,763 @@ +/* + * file-transfer-chan.c - Simple file transfer channel + * + * Copyright (C) 2010-2011 Morten Mjelva <morten.mjelva@gmail.com> + * Copyright (C) 2010-2011 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "file-transfer-chan.h" +#include "util.h" +#include "debug.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +#include <glib/gstdio.h> + +static void file_transfer_iface_init (gpointer iface, gpointer data); + +G_DEFINE_TYPE_WITH_CODE (TpTestsFileTransferChannel, + tp_tests_file_transfer_channel, + TP_TYPE_BASE_CHANNEL, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_FILE_TRANSFER, + file_transfer_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA, + NULL); + ) + +enum /* properties */ +{ + PROP_AVAILABLE_SOCKET_TYPES = 1, + PROP_CONTENT_TYPE, + PROP_CONTENT_HASH, + PROP_CONTENT_HASH_TYPE, + PROP_DATE, + PROP_DESCRIPTION, + PROP_FILENAME, + PROP_INITIAL_OFFSET, + PROP_SIZE, + PROP_STATE, + PROP_TRANSFERRED_BYTES, + PROP_URI, + PROP_SERVICE_NAME, + PROP_METADATA, + N_PROPS, +}; + +struct _TpTestsFileTransferChannelPrivate { + /* Exposed properties */ + gchar *content_type; + guint64 date; + gchar *description; + gchar *filename; + guint64 size; + TpFileTransferState state; + guint64 transferred_bytes; + gchar *uri; + gchar *service_name; + GHashTable *metadata; + + /* Hidden properties */ + TpFileHashType content_hash_type; + gchar *content_hash; + GHashTable *available_socket_types; + gint64 initial_offset; + + /* Accepting side */ + GSocketService *service; + GValue *access_control_param; + + /* Offering side */ + TpSocketAddressType address_type; + GValue *address; + gchar *unix_address; + gchar *unix_tmpdir; + guint connection_id; + TpSocketAccessControl access_control; + + guint timer_id; +}; + +static void +tp_tests_file_transfer_channel_init (TpTestsFileTransferChannel *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), + TP_TESTS_TYPE_FILE_TRANSFER_CHANNEL, TpTestsFileTransferChannelPrivate); +} + +static void +create_available_socket_types (TpTestsFileTransferChannel *self) +{ + TpSocketAccessControl access_control; + GArray *unix_tab; + + g_assert (self->priv->available_socket_types == NULL); + self->priv->available_socket_types = g_hash_table_new_full (NULL, NULL, + NULL, _tp_destroy_socket_control_list); + + /* SocketAddressTypeUnix */ + unix_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl), + 1); + access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; + g_array_append_val (unix_tab, access_control); + + g_hash_table_insert (self->priv->available_socket_types, + GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_UNIX), unix_tab); +} + +static GObject * +constructor (GType type, + guint n_props, + GObjectConstructParam *props) +{ + GObject *object = + G_OBJECT_CLASS (tp_tests_file_transfer_channel_parent_class)->constructor + (type, n_props, props); + TpTestsFileTransferChannel *self = TP_TESTS_FILE_TRANSFER_CHANNEL (object); + + self->priv->state = TP_FILE_TRANSFER_STATE_PENDING; + + if (self->priv->available_socket_types == NULL) + create_available_socket_types (self); + + tp_base_channel_register (TP_BASE_CHANNEL (self)); + + return object; +} + +static void +dispose (GObject *object) +{ + TpTestsFileTransferChannel *self = TP_TESTS_FILE_TRANSFER_CHANNEL (object); + + if (self->priv->timer_id != 0) + { + g_source_remove (self->priv->timer_id); + self->priv->timer_id = 0; + } + + g_free (self->priv->content_hash); + g_free (self->priv->content_type); + g_free (self->priv->description); + g_free (self->priv->filename); + g_free (self->priv->uri); + g_free (self->priv->service_name); + + tp_clear_pointer (&self->priv->address, tp_g_value_slice_free); + tp_clear_pointer (&self->priv->available_socket_types, g_hash_table_unref); + tp_clear_pointer (&self->priv->access_control_param, tp_g_value_slice_free); + tp_clear_pointer (&self->priv->metadata, g_hash_table_unref); + + if (self->priv->unix_address != NULL) + g_unlink (self->priv->unix_address); + + tp_clear_pointer (&self->priv->unix_address, g_free); + + if (self->priv->unix_tmpdir != NULL) + g_rmdir (self->priv->unix_tmpdir); + + tp_clear_pointer (&self->priv->unix_tmpdir, g_free); + + ((GObjectClass *) tp_tests_file_transfer_channel_parent_class)->dispose ( + object); +} + +static void +get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + TpTestsFileTransferChannel *self = (TpTestsFileTransferChannel *) object; + + switch (property_id) + { + case PROP_AVAILABLE_SOCKET_TYPES: + g_value_set_boxed (value, self->priv->available_socket_types); + break; + + case PROP_CONTENT_HASH: + g_value_set_string (value, self->priv->content_hash); + + case PROP_CONTENT_HASH_TYPE: + g_value_set_uint (value, self->priv->content_hash_type); + break; + + case PROP_CONTENT_TYPE: + g_value_set_string (value, self->priv->content_type); + break; + + case PROP_DATE: + g_value_set_uint64 (value, self->priv->date); + break; + + case PROP_DESCRIPTION: + g_value_set_string (value, self->priv->description); + break; + + case PROP_FILENAME: + g_value_set_string (value, self->priv->filename); + break; + + case PROP_INITIAL_OFFSET: + g_value_set_uint64 (value, self->priv->initial_offset); + break; + + case PROP_SIZE: + g_value_set_uint64 (value, self->priv->size); + break; + + case PROP_STATE: + g_value_set_uint (value, self->priv->state); + break; + + case PROP_TRANSFERRED_BYTES: + g_value_set_uint64 (value, self->priv->transferred_bytes); + break; + + case PROP_URI: + g_value_set_string (value, self->priv->uri); + break; + + case PROP_SERVICE_NAME: + g_value_set_string (value, self->priv->service_name); + break; + + case PROP_METADATA: + g_value_set_boxed (value, self->priv->metadata); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + TpTestsFileTransferChannel *self = (TpTestsFileTransferChannel *) object; + + switch (property_id) + { + case PROP_AVAILABLE_SOCKET_TYPES: + self->priv->available_socket_types = g_value_dup_boxed (value); + break; + + case PROP_CONTENT_HASH: + self->priv->content_hash = g_value_dup_string (value); + break; + + case PROP_CONTENT_HASH_TYPE: + break; + + case PROP_CONTENT_TYPE: + self->priv->content_type = g_value_dup_string (value); + break; + + case PROP_DATE: + self->priv->date = g_value_get_uint64 (value); + break; + + case PROP_DESCRIPTION: + self->priv->description = g_value_dup_string (value); + break; + + case PROP_FILENAME: + self->priv->filename = g_value_dup_string (value); + break; + + case PROP_INITIAL_OFFSET: + self->priv->initial_offset = g_value_get_uint64 (value); + break; + + case PROP_SIZE: + self->priv->size = g_value_get_uint64 (value); + break; + + case PROP_STATE: + self->priv->state = g_value_get_uint (value); + break; + + case PROP_TRANSFERRED_BYTES: + self->priv->transferred_bytes = g_value_get_uint64 (value); + break; + + case PROP_URI: + self->priv->uri = g_value_dup_string (value); + break; + + case PROP_SERVICE_NAME: + self->priv->service_name = g_value_dup_string (value); + break; + + case PROP_METADATA: + self->priv->metadata = g_value_dup_boxed (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +channel_close (TpBaseChannel *self) +{ + g_print ("entered channel_close"); + tp_base_channel_destroyed (self); +} + +static void +fill_immutable_properties (TpBaseChannel *self, + GHashTable *properties) +{ + TpBaseChannelClass *klass = TP_BASE_CHANNEL_CLASS ( + tp_tests_file_transfer_channel_parent_class); + + klass->fill_immutable_properties (self, properties); + + tp_dbus_properties_mixin_fill_properties_hash ( + G_OBJECT (self), properties, + TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "AvailableSocketTypes", + TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "ContentType", + TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "Filename", + TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "Size", + TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "Description", + TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "Date", + TP_IFACE_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA, "ServiceName", + TP_IFACE_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA, "Metadata", + NULL); + + /* URI is immutable only for outgoing transfers */ + if (tp_base_channel_is_requested (self)) + { + tp_dbus_properties_mixin_fill_properties_hash (G_OBJECT (self), + properties, + TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "URI", NULL); + } +} + +static void +change_state (TpTestsFileTransferChannel *self, + TpFileTransferState state, + TpFileTransferStateChangeReason reason) +{ + self->priv->state = state; + + tp_svc_channel_type_file_transfer_emit_file_transfer_state_changed (self, + state, reason); +} + +/* This function imitates the beginning of a filetransfer. It sets the state + * to open, and connects to the "incoming" signal of the GSocketService. + */ +static gboolean +start_file_transfer (gpointer data) +{ + TpTestsFileTransferChannel *self = (TpTestsFileTransferChannel *) data; + + DEBUG ("Setting TP_FILE_TRANSFER_STATE_OPEN"); + change_state (self, TP_FILE_TRANSFER_STATE_OPEN, + TP_FILE_TRANSFER_STATE_CHANGE_REASON_REQUESTED); + + g_object_notify ((GObject *) data, "state"); + DEBUG ("Fired state signal"); + +// g_signal_connect (self->priv->service, "incoming", G_CALLBACK +// (incoming_file_transfer_cb)); + + self->priv->timer_id = 0; + return FALSE; +} + +static gboolean +check_address_type (TpTestsFileTransferChannel *self, + TpSocketAddressType address_type, + TpSocketAccessControl access_control) +{ + GArray *arr; + guint i; + + arr = g_hash_table_lookup (self->priv->available_socket_types, + GUINT_TO_POINTER (address_type)); + if (arr == NULL) + return FALSE; + + for (i = 0; i < arr->len; i++) + { + if (g_array_index (arr, TpSocketAccessControl, i) == access_control) + return TRUE; + } + + return FALSE; +} + +static void +service_incoming_cb (GSocketService *service, + GSocketConnection *connection, + GObject *source_object, + gpointer user_data) +{ + TpTestsFileTransferChannel *self = user_data; + GError *error = NULL; + + DEBUG ("Servicing incoming connection"); + if (self->priv->access_control == TP_SOCKET_ACCESS_CONTROL_CREDENTIALS) + { + GCredentials *creds; + guchar byte; + + /* TODO: Async version */ + creds = tp_unix_connection_receive_credentials_with_byte ( + connection, &byte, NULL, &error); + g_assert_no_error (error); + + g_assert_cmpuint (byte, ==, + g_value_get_uchar (self->priv->access_control_param)); + g_object_unref (creds); + } + else if (self->priv->access_control == TP_SOCKET_ACCESS_CONTROL_PORT) + { + GSocketAddress *addr; + guint16 port; + + addr = g_socket_connection_get_remote_address (connection, &error); + g_assert_no_error (error); + + port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); + + g_assert_cmpuint (port, ==, + g_value_get_uint (self->priv->access_control_param)); + + g_object_unref (addr); + } +} + +static void +file_transfer_provide_file (TpSvcChannelTypeFileTransfer *iface, + TpSocketAddressType address_type, + TpSocketAccessControl access_control, + const GValue *access_control_param, + DBusGMethodInvocation *context) +{ + TpTestsFileTransferChannel *self = (TpTestsFileTransferChannel *) iface; + TpBaseChannel *base_chan = (TpBaseChannel *) iface; + GError *error = NULL; + + if (tp_base_channel_is_requested (base_chan) != TRUE) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "File transfer is not outgoing. Cannot offer file"); + goto fail; + } + + if (self->priv->state != TP_FILE_TRANSFER_STATE_PENDING && + self->priv->state != TP_FILE_TRANSFER_STATE_ACCEPTED) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "File transfer is not pending or accepted. Cannot offer file"); + goto fail; + } + + if (self->priv->address != NULL) + { + g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, + "ProvideFile has already been called for this channel"); + goto fail; + } + + if (!check_address_type (self, address_type, access_control)) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Address type %i is not supported with access control %i", + address_type, access_control); + goto fail; + } + + self->priv->address = _tp_create_local_socket (address_type, access_control, + &self->priv->service, &self->priv->unix_address, + &self->priv->unix_tmpdir, &error); + + if (self->priv->address == NULL) + { + g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, + "Could not set up local socket"); + goto fail; + } + + self->priv->address_type = address_type; + self->priv->access_control = access_control; + + DEBUG ("Waiting 500ms and setting state to OPEN"); + self->priv->timer_id = g_timeout_add (500, start_file_transfer, self); + + // connect to self->priv->service incoming signal + // when the signal returns, add x bytes per n seconds using timeout + // then close the socket + // g_output_stream_write_async + + tp_svc_channel_type_file_transfer_return_from_provide_file (context, + self->priv->address); + + return; + +fail: + dbus_g_method_return_error (context, error); + g_error_free (error); +} + +static void +file_transfer_accept_file (TpSvcChannelTypeFileTransfer *iface, + TpSocketAddressType address_type, + TpSocketAccessControl access_control, + const GValue *access_control_param, + guint64 offset, + DBusGMethodInvocation *context) +{ + TpTestsFileTransferChannel *self = (TpTestsFileTransferChannel *) iface; + TpBaseChannel *base_chan = (TpBaseChannel *) iface; + GError *error = NULL; + GValue *address; + + if (tp_base_channel_is_requested (base_chan) == TRUE) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "File transfer is not incoming. Cannot accept file"); + goto fail; + } + + if (self->priv->state != TP_FILE_TRANSFER_STATE_PENDING) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "File transfer is not in the pending state"); + goto fail; + } + + if (!check_address_type (self, address_type, access_control)) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Address type %i is not supported with access control %i", + address_type, access_control); + goto fail; + } + + address = _tp_create_local_socket (address_type, access_control, + &self->priv->service, &self->priv->unix_address, + &self->priv->unix_tmpdir, &error); + + tp_g_signal_connect_object (self->priv->service, "incoming", + G_CALLBACK (service_incoming_cb), self, 0); + + self->priv->access_control = access_control; + self->priv->access_control_param = tp_g_value_slice_dup ( + access_control_param); + + DEBUG ("Setting TP_FILE_TRANSFER_STATE_ACCEPTED"); + change_state (self, TP_FILE_TRANSFER_STATE_ACCEPTED, + TP_FILE_TRANSFER_STATE_CHANGE_REASON_REQUESTED); + + DEBUG ("Waiting 500ms and setting state to OPEN"); + self->priv->timer_id = g_timeout_add (500, start_file_transfer, self); + + tp_svc_channel_type_file_transfer_return_from_accept_file (context, + address); + + tp_clear_pointer (&address, tp_g_value_slice_free); + + return; + +fail: + dbus_g_method_return_error (context, error); + g_error_free (error); +} + +static void +tp_tests_file_transfer_channel_class_init ( + TpTestsFileTransferChannelClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + GParamSpec *param_spec; + + static TpDBusPropertiesMixinPropImpl file_transfer_props[] = { + { "AvailableSocketTypes", "available-socket-types", NULL }, + { "ContentType", "content-type", NULL }, + { "Date", "date", NULL }, + { "Description", "description", NULL }, + { "Filename", "filename", NULL }, + { "Size", "size", NULL }, + { "State", "state", NULL }, + { "TransferredBytes", "transferred-bytes", NULL }, + { "URI", "uri", NULL }, + { NULL } + }; + + static TpDBusPropertiesMixinPropImpl metadata_props[] = { + { "ServiceName", "service-name", NULL }, + { "Metadata", "metadata", NULL }, + { NULL } + }; + + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + + base_class->channel_type = TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER; + base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; + + base_class->close = channel_close; + base_class->fill_immutable_properties = fill_immutable_properties; + + param_spec = g_param_spec_boxed ("available-socket-types", + "AvailableSocketTypes", + "The AvailableSocketTypes property of this channel", + TP_HASH_TYPE_SUPPORTED_SOCKET_MAP, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_AVAILABLE_SOCKET_TYPES, + param_spec); + + param_spec = g_param_spec_string ("content-type", + "ContentType", + "The ContentType property of this channel", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_CONTENT_TYPE, + param_spec); + + param_spec = g_param_spec_uint64 ("date", + "Date", + "The Date property of this channel", + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_DATE, + param_spec); + + param_spec = g_param_spec_string ("description", + "Description", + "The Description property of this channel", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_DESCRIPTION, + param_spec); + + param_spec = g_param_spec_string ("filename", + "Filename", + "The Filename property of this channel", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_FILENAME, + param_spec); + + param_spec = g_param_spec_uint64 ("initial-offset", + "InitialOffset", + "The InitialOffset property of this channel", + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_INITIAL_OFFSET, + param_spec); + + param_spec = g_param_spec_uint64 ("size", + "Size", + "The Size property of this channel", + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_SIZE, + param_spec); + + param_spec = g_param_spec_uint ("state", + "State", + "The State property of this channel", + 0, TP_NUM_FILE_TRANSFER_STATES, TP_FILE_TRANSFER_STATE_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_STATE, + param_spec); + + param_spec = g_param_spec_uint64 ("transferred-bytes", + "TransferredBytes", + "The TransferredBytes property of this channel", + 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_TRANSFERRED_BYTES, + param_spec); + + param_spec = g_param_spec_string ("uri", + "URI", + "The URI property of this channel", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_URI, + param_spec); + + param_spec = g_param_spec_string ("service-name", + "ServiceName", + "The Metadata.ServiceName property of this channel", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_SERVICE_NAME, + param_spec); + + param_spec = g_param_spec_boxed ("metadata", + "Metadata", + "The Metadata.Metadata property of this channel", + TP_HASH_TYPE_METADATA, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_METADATA, + param_spec); + + tp_dbus_properties_mixin_implement_interface (object_class, + TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER, + tp_dbus_properties_mixin_getter_gobject_properties, NULL, + file_transfer_props); + + tp_dbus_properties_mixin_implement_interface (object_class, + TP_IFACE_QUARK_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA, + tp_dbus_properties_mixin_getter_gobject_properties, NULL, + metadata_props); + + g_type_class_add_private (object_class, + sizeof (TpTestsFileTransferChannelPrivate)); +} + +static void +file_transfer_iface_init (gpointer iface, gpointer data) +{ + TpSvcChannelTypeFileTransferClass *klass = iface; + +#define IMPLEMENT(x) tp_svc_channel_type_file_transfer_implement_##x (klass, \ + file_transfer_##x) + IMPLEMENT(accept_file); + IMPLEMENT(provide_file); +#undef IMPLEMENT +} + +/* Return the address of the file transfer's socket */ +GSocketAddress * +tp_tests_file_transfer_channel_get_server_address ( + TpTestsFileTransferChannel *self) +{ + GSocketAddress *address; + GError *error = NULL; + + g_assert (self->priv->address != NULL); + + address = tp_g_socket_address_from_variant (self->priv->address_type, + self->priv->address, &error); + + if (error != NULL) + { + g_printf ("%s\n", error->message); + } + + return address; +} diff --git a/tests/lib/telepathy/contactlist/file-transfer-chan.h b/tests/lib/telepathy/contactlist/file-transfer-chan.h new file mode 100644 index 00000000..19d6c98a --- /dev/null +++ b/tests/lib/telepathy/contactlist/file-transfer-chan.h @@ -0,0 +1,63 @@ +/* + * stream-tube-chan.h - Simple stream tube channel + * + * Copyright (C) 2010-2011 Morten Mjelva <morten.mjelva@gmail.com> + * Copyright (C) 2010-2011 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_FILE_TRANSFER_CHAN_H__ +#define __TP_FILE_TRANSFER_CHAN_H__ + +#include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + +G_BEGIN_DECLS + +typedef struct _TpTestsFileTransferChannel TpTestsFileTransferChannel; +typedef struct _TpTestsFileTransferChannelClass TpTestsFileTransferChannelClass; +typedef struct _TpTestsFileTransferChannelPrivate TpTestsFileTransferChannelPrivate; + +GType tp_tests_file_transfer_channel_get_type (void); + +#define TP_TESTS_TYPE_FILE_TRANSFER_CHANNEL \ + (tp_tests_file_transfer_channel_get_type ()) +#define TP_TESTS_FILE_TRANSFER_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_FILE_TRANSFER_CHANNEL, \ + TpTestsFileTransferChannel)) +#define TP_TESTS_FILE_TRANSFER_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_FILE_TRANSFER_CHANNEL, \ + TpTestsFileTransferChannelClass)) +#define TP_TESTS_IS_FILE_TRANSFER_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_FILE_TRANSFER_CHANNEL)) +#define TP_TESTS_IS_FILE_TRANSFER_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_FILE_TRANSFER_CHANNEL)) +#define TP_TESTS_FILE_TRANSFER_CHANNEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_FILE_TRANSFER_CHANNEL, \ + TpTestsFileTransferChannelClass)) + +struct _TpTestsFileTransferChannelClass { + TpBaseChannelClass parent_class; + TpDBusPropertiesMixinClass dbus_properties_class; +}; + +struct _TpTestsFileTransferChannel { + TpBaseChannel parent; + + TpTestsFileTransferChannelPrivate *priv; +}; + +void tp_tests_file_transfer_channel_close (TpTestsFileTransferChannel *self); + +GHashTable * tp_tests_file_transfer_channel_get_props ( + TpTestsFileTransferChannel *self); + +GSocketAddress * tp_tests_file_transfer_channel_get_server_address ( + TpTestsFileTransferChannel *self); + +G_END_DECLS + +#endif diff --git a/tests/lib/telepathy/contactlist/my-conn-proxy.c b/tests/lib/telepathy/contactlist/my-conn-proxy.c new file mode 100644 index 00000000..0d7723c4 --- /dev/null +++ b/tests/lib/telepathy/contactlist/my-conn-proxy.c @@ -0,0 +1,364 @@ +/* + * my-conn-proxy.c - a simple subclass of TpConnection + * + * Copyright (C) 2010-2011 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "my-conn-proxy.h" + +#include <telepathy-glib/telepathy-glib.h> + +G_DEFINE_TYPE (TpTestsMyConnProxy, tp_tests_my_conn_proxy, + TP_TYPE_CONNECTION) + +static void +tp_tests_my_conn_proxy_init (TpTestsMyConnProxy *self) +{ +} + +enum { + FEAT_CORE, + FEAT_A, + FEAT_B, + FEAT_WRONG_IFACE, + FEAT_BAD_DEP, + FEAT_FAIL, + FEAT_FAIL_DEP, + FEAT_RETRY, + FEAT_RETRY_DEP, + FEAT_BEFORE_CONNECTED, + FEAT_INTERFACE_LATER, + N_FEAT +}; + +static void +prepare_core_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + /* superclass core features are prepared first */ + g_assert (tp_proxy_is_prepared (proxy, TP_CONNECTION_FEATURE_CORE)); + + result = g_simple_async_result_new ((GObject *) proxy, callback, user_data, + prepare_core_async); + + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static void +prepare_a_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE)); + + result = g_simple_async_result_new ((GObject *) proxy, callback, user_data, + prepare_a_async); + + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static void +prepare_b_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE)); + g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_A)); + + result = g_simple_async_result_new ((GObject *) proxy, callback, user_data, + prepare_b_async); + + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static void +cannot_be_prepared_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_assert_not_reached (); +} + +static void +prepare_fail_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE)); + + result = g_simple_async_result_new_error ((GObject *) proxy, callback, + user_data, TP_ERROR, TP_ERROR_NOT_AVAILABLE, + "No feature for you!"); + + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static void +prepare_retry_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + TpTestsMyConnProxy *self = (TpTestsMyConnProxy *) proxy; + GSimpleAsyncResult *result; + + result = g_simple_async_result_new ((GObject *) proxy, callback, user_data, + prepare_retry_async); + + if (!self->retry_feature_success) + { + /* Fail the first time we try to prepare the feature */ + g_simple_async_result_set_error (result, TP_ERROR, + TP_ERROR_NOT_YET, "Nah"); + } + + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static void +prepare_retry_dep_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE)); + + result = g_simple_async_result_new ((GObject *) proxy, callback, user_data, + prepare_retry_dep_async); + + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static void +prepare_before_connected_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + TpTestsMyConnProxy *self = (TpTestsMyConnProxy *) proxy; + GSimpleAsyncResult *result; + + g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE)); + + result = g_simple_async_result_new ((GObject *) proxy, callback, user_data, + prepare_before_connected_async); + + if (tp_connection_get_status (TP_CONNECTION (self), NULL) == + TP_CONNECTION_STATUS_CONNECTED) + self->before_connected_state = BEFORE_CONNECTED_STATE_CONNECTED; + else + self->before_connected_state = BEFORE_CONNECTED_STATE_NOT_CONNECTED; + + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static void +prepare_before_connected_before_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + TpTestsMyConnProxy *self = (TpTestsMyConnProxy *) proxy; + GSimpleAsyncResult *result; + + g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE)); + + g_assert_cmpuint (tp_connection_get_status (TP_CONNECTION (proxy), NULL), ==, + TP_CONNECTION_STATUS_CONNECTING); + + result = g_simple_async_result_new ((GObject *) proxy, callback, user_data, + prepare_before_connected_before_async); + + self->before_connected_state = BEFORE_CONNECTED_STATE_CONNECTED; + + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static void +prepare_interface_later_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + result = g_simple_async_result_new ((GObject *) proxy, callback, user_data, + prepare_interface_later_async); + + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +static const TpProxyFeature * +list_features (TpProxyClass *cls G_GNUC_UNUSED) +{ + static TpProxyFeature features[N_FEAT + 1] = { { 0 } }; + static GQuark need_a[2] = {0, 0}; + static GQuark need_channel_core[2] = {0, 0}; + static GQuark need_wrong_iface[2] = {0, 0}; + static GQuark need_fail[2] = {0, 0}; + static GQuark need_retry[2] = {0, 0}; + static GQuark need_iface_later[2] = {0, 0}; + + if (G_LIKELY (features[0].name != 0)) + return features; + + features[FEAT_CORE].name = TP_TESTS_MY_CONN_PROXY_FEATURE_CORE; + features[FEAT_CORE].core = TRUE; + features[FEAT_CORE].prepare_async = prepare_core_async; + + features[FEAT_A].name = TP_TESTS_MY_CONN_PROXY_FEATURE_A; + features[FEAT_A].prepare_async = prepare_a_async; + + features[FEAT_B].name = TP_TESTS_MY_CONN_PROXY_FEATURE_B; + features[FEAT_B].prepare_async = prepare_b_async; + need_a[0] = TP_TESTS_MY_CONN_PROXY_FEATURE_A; + features[FEAT_B].depends_on = need_a; + + features[FEAT_WRONG_IFACE].name = TP_TESTS_MY_CONN_PROXY_FEATURE_WRONG_IFACE; + features[FEAT_WRONG_IFACE].prepare_async = cannot_be_prepared_async; + need_channel_core[0] = TP_CHANNEL_FEATURE_CORE; + features[FEAT_WRONG_IFACE].interfaces_needed = need_channel_core; + + features[FEAT_BAD_DEP].name = TP_TESTS_MY_CONN_PROXY_FEATURE_BAD_DEP; + features[FEAT_BAD_DEP].prepare_async = cannot_be_prepared_async; + need_wrong_iface[0] = TP_TESTS_MY_CONN_PROXY_FEATURE_WRONG_IFACE; + features[FEAT_BAD_DEP].depends_on = need_wrong_iface; + + features[FEAT_FAIL].name = TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL; + features[FEAT_FAIL].prepare_async = prepare_fail_async; + + features[FEAT_FAIL_DEP].name = TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL_DEP; + features[FEAT_FAIL_DEP].prepare_async = cannot_be_prepared_async; + need_fail[0] = TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL; + features[FEAT_FAIL_DEP].depends_on = need_fail; + + features[FEAT_RETRY].name = TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY; + features[FEAT_RETRY].prepare_async = prepare_retry_async; + features[FEAT_RETRY].can_retry = TRUE; + + features[FEAT_RETRY_DEP].name = TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY_DEP; + need_retry[0] = TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY; + features[FEAT_RETRY_DEP].prepare_async = prepare_retry_dep_async; + features[FEAT_RETRY_DEP].depends_on = need_retry; + + features[FEAT_BEFORE_CONNECTED].name = + TP_TESTS_MY_CONN_PROXY_FEATURE_BEFORE_CONNECTED; + features[FEAT_BEFORE_CONNECTED].prepare_async = + prepare_before_connected_async; + features[FEAT_BEFORE_CONNECTED].prepare_before_signalling_connected_async = + prepare_before_connected_before_async; + + features[FEAT_INTERFACE_LATER].name = + TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER; + features[FEAT_INTERFACE_LATER].prepare_async = prepare_interface_later_async; + need_iface_later[0] = g_quark_from_static_string ( + TP_TESTS_MY_CONN_PROXY_IFACE_LATER); + features[FEAT_INTERFACE_LATER].interfaces_needed = need_iface_later; + + return features; +} + +static void +tp_tests_my_conn_proxy_class_init (TpTestsMyConnProxyClass *klass) +{ + TpProxyClass *proxy_class = (TpProxyClass *) klass; + + proxy_class->list_features = list_features; +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_core (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-core"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_a (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-a"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_b (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-b"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_wrong_iface (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-wrong_iface"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_bad_dep (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-bad-dep"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_fail (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-fail"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_fail_dep (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-fail-dep"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_retry (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-retry"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_retry_dep (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-retry-dep"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_before_connected (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-before-connected"); +} + +GQuark +tp_tests_my_conn_proxy_get_feature_quark_interface_later (void) +{ + return g_quark_from_static_string ("tp-my-conn-proxy-feature-interface-later"); +} diff --git a/tests/lib/telepathy/contactlist/my-conn-proxy.h b/tests/lib/telepathy/contactlist/my-conn-proxy.h new file mode 100644 index 00000000..08be18b9 --- /dev/null +++ b/tests/lib/telepathy/contactlist/my-conn-proxy.h @@ -0,0 +1,124 @@ +/* + * my-conn-proxy.h - header for a simple subclass of TpConnection + * + * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_MY_CONN_PROXY_H__ +#define __TP_TESTS_MY_CONN_PROXY_H__ + +#include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + + +G_BEGIN_DECLS + +typedef struct _TpTestsMyConnProxy TpTestsMyConnProxy; +typedef struct _TpTestsMyConnProxyClass TpTestsMyConnProxyClass; +typedef struct _TpTestsMyConnProxyPrivate TpTestsMyConnProxyPrivate; + +struct _TpTestsMyConnProxyClass { + TpConnectionClass parent_class; +}; + +typedef enum +{ + BEFORE_CONNECTED_STATE_UNPREPARED = 0, + BEFORE_CONNECTED_STATE_NOT_CONNECTED, + BEFORE_CONNECTED_STATE_CONNECTED, +} TpTestsMyConnProxyBeforeConnectedState; + + +struct _TpTestsMyConnProxy { + TpConnection parent; + + gboolean retry_feature_success; + TpTestsMyConnProxyBeforeConnectedState before_connected_state; +}; + +GType tp_tests_my_conn_proxy_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_MY_CONN_PROXY \ + (tp_tests_my_conn_proxy_get_type ()) +#define TP_TESTS_MY_CONN_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_MY_CONN_PROXY, \ + TpTestsMyConnProxy)) +#define TP_TESTS_MY_CONN_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_MY_CONN_PROXY, \ + TpTestsMyConnProxyClass)) +#define TP_TESTS_SIMPLE_IS_MY_CONN_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_MY_CONN_PROXY)) +#define TP_TESTS_SIMPLE_IS_MY_CONN_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_MY_CONN_PROXY)) +#define TP_TESTS_MY_CONN_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_MY_CONN_PROXY, \ + TpTestsMyConnProxyClass)) + +/* Core feature */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_CORE \ + (tp_tests_my_conn_proxy_get_feature_quark_core ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_core (void) G_GNUC_CONST; + +/* No depends */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_A \ + (tp_tests_my_conn_proxy_get_feature_quark_a ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_a (void) G_GNUC_CONST; + +/* Depends on A */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_B \ + (tp_tests_my_conn_proxy_get_feature_quark_b ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_b (void) G_GNUC_CONST; + +/* Depends on an unimplemented iface */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_WRONG_IFACE \ + (tp_tests_my_conn_proxy_get_feature_quark_wrong_iface ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_wrong_iface (void) G_GNUC_CONST; + +/* Depends on WRONG_IFACE */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_BAD_DEP \ + (tp_tests_my_conn_proxy_get_feature_quark_bad_dep ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_bad_dep (void) G_GNUC_CONST; + +/* Fail during preparation */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL \ + (tp_tests_my_conn_proxy_get_feature_quark_fail ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_fail (void) G_GNUC_CONST; + +/* Depends on FAIL */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL_DEP \ + (tp_tests_my_conn_proxy_get_feature_quark_fail_dep ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_fail_dep (void) G_GNUC_CONST; + +/* Fail at first attempt but succeed after */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY \ + (tp_tests_my_conn_proxy_get_feature_quark_retry ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_retry (void) G_GNUC_CONST; + +/* Depends on FEATURE_RETRY */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY_DEP \ + (tp_tests_my_conn_proxy_get_feature_quark_retry_dep ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_retry_dep (void) G_GNUC_CONST; + +/* Can be prepared before the connection is connected and block announcing the + * connected state */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_BEFORE_CONNECTED \ + (tp_tests_my_conn_proxy_get_feature_quark_before_connected ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_before_connected (void) G_GNUC_CONST; + +#define TP_TESTS_MY_CONN_PROXY_IFACE_LATER "org.freedesktop.Telepathy.Conncetion.Interface.Test.Later" + +/* Need the interface TP_TESTS_MY_CONN_PROXY_IFACE_LATER to be prepared but + * this interface is not in the initial set of interfaces of the connection. + * It is added when the connection is connected. */ +#define TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER \ + (tp_tests_my_conn_proxy_get_feature_quark_interface_later ()) +GQuark tp_tests_my_conn_proxy_get_feature_quark_interface_later (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_MY_CONN_PROXY_H__ */ diff --git a/tests/lib/telepathy/contactlist/myassert.h b/tests/lib/telepathy/contactlist/myassert.h new file mode 100644 index 00000000..1fd6fd3b --- /dev/null +++ b/tests/lib/telepathy/contactlist/myassert.h @@ -0,0 +1,16 @@ +#ifndef TP_TESTS_MYASSERT_H +#define TP_TESTS_MYASSERT_H + +#include <glib.h> +#include <telepathy-glib/telepathy-glib.h> + +#define MYASSERT(assertion, extra_format, ...)\ + G_STMT_START {\ + if (!(assertion))\ + {\ + g_error ("\n%s:%d: Assertion failed: %s" extra_format,\ + __FILE__, __LINE__, #assertion, ##__VA_ARGS__);\ + }\ + } G_STMT_END + +#endif diff --git a/tests/lib/telepathy/contactlist/room-list-chan.c b/tests/lib/telepathy/contactlist/room-list-chan.c index 49ed291a..f4db0670 100644 --- a/tests/lib/telepathy/contactlist/room-list-chan.c +++ b/tests/lib/telepathy/contactlist/room-list-chan.c @@ -4,8 +4,7 @@ #include "room-list-chan.h" #include <telepathy-glib/telepathy-glib.h> -#include <telepathy-glib/channel-iface.h> -#include <telepathy-glib/svc-channel.h> +#include <telepathy-glib/telepathy-glib-dbus.h> static void room_list_iface_init (gpointer iface, gpointer data); diff --git a/tests/lib/telepathy/contactlist/room-list-chan.h b/tests/lib/telepathy/contactlist/room-list-chan.h index b41be273..52dbd2e8 100644 --- a/tests/lib/telepathy/contactlist/room-list-chan.h +++ b/tests/lib/telepathy/contactlist/room-list-chan.h @@ -3,7 +3,7 @@ #define __TP_TESTS_ROOM_LIST_CHAN_H__ #include <glib-object.h> -#include <telepathy-glib/base-channel.h> +#include <telepathy-glib/telepathy-glib.h> G_BEGIN_DECLS diff --git a/tests/lib/telepathy/contactlist/simple-account-manager.c b/tests/lib/telepathy/contactlist/simple-account-manager.c index e1fec674..e5bddbc1 100644 --- a/tests/lib/telepathy/contactlist/simple-account-manager.c +++ b/tests/lib/telepathy/contactlist/simple-account-manager.c @@ -13,12 +13,8 @@ #include "simple-account-manager.h" -#include <telepathy-glib/account.h> -#include <telepathy-glib/gtypes.h> -#include <telepathy-glib/interfaces.h> -#include <telepathy-glib/svc-generic.h> -#include <telepathy-glib/svc-account-manager.h> -#include <telepathy-glib/util.h> +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> static void account_manager_iface_init (gpointer, gpointer); @@ -39,14 +35,14 @@ enum { PROP_0, PROP_INTERFACES, - PROP_VALID_ACCOUNTS, - PROP_INVALID_ACCOUNTS, + PROP_USABLE_ACCOUNTS, + PROP_UNUSABLE_ACCOUNTS, }; struct _TpTestsSimpleAccountManagerPrivate { - GPtrArray *valid_accounts; - GPtrArray *invalid_accounts; + GPtrArray *usable_accounts; + GPtrArray *unusable_accounts; }; static void @@ -95,8 +91,8 @@ tp_tests_simple_account_manager_init (TpTestsSimpleAccountManager *self) self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_SIMPLE_ACCOUNT_MANAGER, TpTestsSimpleAccountManagerPrivate); - self->priv->valid_accounts = g_ptr_array_new_with_free_func (g_free); - self->priv->invalid_accounts = g_ptr_array_new_with_free_func (g_free); + self->priv->usable_accounts = g_ptr_array_new_with_free_func (g_free); + self->priv->unusable_accounts = g_ptr_array_new_with_free_func (g_free); } static void @@ -112,12 +108,12 @@ tp_tests_simple_account_manager_get_property (GObject *object, g_value_set_boxed (value, ACCOUNT_MANAGER_INTERFACES); break; - case PROP_VALID_ACCOUNTS: - g_value_set_boxed (value, self->priv->valid_accounts); + case PROP_USABLE_ACCOUNTS: + g_value_set_boxed (value, self->priv->usable_accounts); break; - case PROP_INVALID_ACCOUNTS: - g_value_set_boxed (value, self->priv->invalid_accounts); + case PROP_UNUSABLE_ACCOUNTS: + g_value_set_boxed (value, self->priv->unusable_accounts); break; default: @@ -131,8 +127,8 @@ tp_tests_simple_account_manager_finalize (GObject *object) { TpTestsSimpleAccountManager *self = SIMPLE_ACCOUNT_MANAGER (object); - g_ptr_array_unref (self->priv->valid_accounts); - g_ptr_array_unref (self->priv->invalid_accounts); + g_ptr_array_unref (self->priv->usable_accounts); + g_ptr_array_unref (self->priv->unusable_accounts); tp_clear_pointer (&self->create_cm, g_free); tp_clear_pointer (&self->create_protocol, g_free); @@ -160,8 +156,8 @@ tp_tests_simple_account_manager_class_init ( static TpDBusPropertiesMixinPropImpl am_props[] = { { "Interfaces", "interfaces", NULL }, - { "ValidAccounts", "valid-accounts", NULL }, - { "InvalidAccounts", "invalid-accounts", NULL }, + { "UsableAccounts", "usable-accounts", NULL }, + { "UnusableAccounts", "unusable-accounts", NULL }, /* { "SupportedAccountProperties", "supported-account-properties", NULL }, */ @@ -186,16 +182,16 @@ tp_tests_simple_account_manager_class_init ( G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); - param_spec = g_param_spec_boxed ("valid-accounts", "Valid accounts", - "The accounts which are valid on this account. This may be a lie.", + param_spec = g_param_spec_boxed ("usable-accounts", "Usable accounts", + "The accounts which are usable on this account manager. This may be a lie.", TP_ARRAY_TYPE_OBJECT_PATH_LIST, G_PARAM_READABLE); - g_object_class_install_property (object_class, PROP_VALID_ACCOUNTS, param_spec); - param_spec = g_param_spec_boxed ("invalid-accounts", "Invalid accounts", - "The accounts which are invalid on this account. This may be a lie.", + g_object_class_install_property (object_class, PROP_USABLE_ACCOUNTS, param_spec); + param_spec = g_param_spec_boxed ("unusable-accounts", "Unusable accounts", + "The accounts which are unusable on this account manager. This may be a lie.", TP_ARRAY_TYPE_OBJECT_PATH_LIST, G_PARAM_READABLE); - g_object_class_install_property (object_class, PROP_INVALID_ACCOUNTS, param_spec); + g_object_class_install_property (object_class, PROP_UNUSABLE_ACCOUNTS, param_spec); klass->dbus_props_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, @@ -219,17 +215,18 @@ void tp_tests_simple_account_manager_add_account ( TpTestsSimpleAccountManager *self, const gchar *object_path, - gboolean valid) + gboolean usable) { - remove_from_array (self->priv->valid_accounts, object_path); - remove_from_array (self->priv->valid_accounts, object_path); + remove_from_array (self->priv->usable_accounts, object_path); + remove_from_array (self->priv->unusable_accounts, object_path); - if (valid) - g_ptr_array_add (self->priv->valid_accounts, g_strdup (object_path)); + if (usable) + g_ptr_array_add (self->priv->usable_accounts, g_strdup (object_path)); else - g_ptr_array_add (self->priv->invalid_accounts, g_strdup (object_path)); + g_ptr_array_add (self->priv->unusable_accounts, g_strdup (object_path)); - tp_svc_account_manager_emit_account_validity_changed (self, object_path, valid); + tp_svc_account_manager_emit_account_usability_changed (self, object_path, + usable); } void @@ -237,8 +234,8 @@ tp_tests_simple_account_manager_remove_account ( TpTestsSimpleAccountManager *self, const gchar *object_path) { - remove_from_array (self->priv->valid_accounts, object_path); - remove_from_array (self->priv->valid_accounts, object_path); + remove_from_array (self->priv->usable_accounts, object_path); + remove_from_array (self->priv->unusable_accounts, object_path); tp_svc_account_manager_emit_account_removed (self, object_path); } diff --git a/tests/lib/telepathy/contactlist/simple-account-manager.h b/tests/lib/telepathy/contactlist/simple-account-manager.h index d1608d51..cc65f092 100644 --- a/tests/lib/telepathy/contactlist/simple-account-manager.h +++ b/tests/lib/telepathy/contactlist/simple-account-manager.h @@ -13,7 +13,7 @@ #define __TP_TESTS_SIMPLE_ACCOUNT_MANAGER_H__ #include <glib-object.h> -#include <telepathy-glib/dbus-properties-mixin.h> +#include <telepathy-glib/telepathy-glib.h> G_BEGIN_DECLS @@ -61,7 +61,7 @@ GType tp_tests_simple_account_manager_get_type (void); void tp_tests_simple_account_manager_add_account ( TpTestsSimpleAccountManager *self, const gchar *object_path, - gboolean valid); + gboolean usable); void tp_tests_simple_account_manager_remove_account ( TpTestsSimpleAccountManager *self, diff --git a/tests/lib/telepathy/contactlist/simple-account.c b/tests/lib/telepathy/contactlist/simple-account.c index 6279d755..8b13268b 100644 --- a/tests/lib/telepathy/contactlist/simple-account.c +++ b/tests/lib/telepathy/contactlist/simple-account.c @@ -12,14 +12,8 @@ #include "simple-account.h" -#include <telepathy-glib/dbus.h> -#include <telepathy-glib/defs.h> -#include <telepathy-glib/enums.h> -#include <telepathy-glib/gtypes.h> -#include <telepathy-glib/interfaces.h> -#include <telepathy-glib/util.h> -#include <telepathy-glib/svc-generic.h> -#include <telepathy-glib/svc-account.h> +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> static void account_iface_init (gpointer, gpointer); @@ -50,7 +44,7 @@ enum PROP_INTERFACES, PROP_DISPLAY_NAME, PROP_ICON, - PROP_VALID, + PROP_USABLE, PROP_ENABLED, PROP_NICKNAME, PROP_PARAMETERS, @@ -80,6 +74,7 @@ struct _TpTestsSimpleAccountPrivate gchar *presence_msg; gchar *connection_path; gboolean enabled; + GPtrArray *uri_schemes; }; static void @@ -122,10 +117,14 @@ account_iface_init (gpointer klass, #undef IMPLEMENT } +/* you may have noticed this is not entirely realistic */ +static const gchar * const uri_schemes[] = { "about", "telnet", NULL }; static void tp_tests_simple_account_init (TpTestsSimpleAccount *self) { + guint i; + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_SIMPLE_ACCOUNT, TpTestsSimpleAccountPrivate); @@ -134,10 +133,11 @@ tp_tests_simple_account_init (TpTestsSimpleAccount *self) self->priv->presence_msg = g_strdup ("this is my CurrentPresence"); self->priv->connection_path = g_strdup ("/"); self->priv->enabled = TRUE; -} -/* you may have noticed this is not entirely realistic */ -static const gchar * const uri_schemes[] = { "about", "telnet", NULL }; + self->priv->uri_schemes = g_ptr_array_new_with_free_func (g_free); + for (i = 0; uri_schemes[i] != NULL; i++) + g_ptr_array_add (self->priv->uri_schemes, g_strdup (uri_schemes[i])); +} static void tp_tests_simple_account_get_property (GObject *object, @@ -161,7 +161,7 @@ tp_tests_simple_account_get_property (GObject *object, case PROP_ICON: g_value_set_string (value, ""); break; - case PROP_VALID: + case PROP_USABLE: g_value_set_boolean (value, TRUE); break; case PROP_ENABLED: @@ -213,7 +213,7 @@ tp_tests_simple_account_get_property (GObject *object, g_value_set_boolean (value, TRUE); break; case PROP_STORAGE_PROVIDER: - g_value_set_string (value, "org.freedesktop.Telepathy.glib.test"); + g_value_set_string (value, "im.telepathy1.glib.test"); break; case PROP_STORAGE_IDENTIFIER: g_value_set_boxed (value, &identifier); @@ -231,7 +231,19 @@ tp_tests_simple_account_get_property (GObject *object, TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PARAMETERS); break; case PROP_URI_SCHEMES: - g_value_set_boxed (value, uri_schemes); + { + GPtrArray *arr; + guint i; + + arr = g_ptr_array_sized_new (self->priv->uri_schemes->len + 1); + for (i = 0; i < self->priv->uri_schemes->len; i++) + g_ptr_array_add (arr, + g_ptr_array_index (self->priv->uri_schemes, i)); + g_ptr_array_add (arr, NULL); + + g_value_set_boxed (value, arr->pdata); + g_ptr_array_unref (arr); + } break; case PROP_AVATAR: { @@ -274,6 +286,8 @@ tp_tests_simple_account_finalize (GObject *object) g_free (self->priv->presence_msg); g_free (self->priv->connection_path); + g_ptr_array_unref (self->priv->uri_schemes); + G_OBJECT_CLASS (tp_tests_simple_account_parent_class)->finalize (object); } @@ -292,7 +306,7 @@ tp_tests_simple_account_class_init (TpTestsSimpleAccountClass *klass) { "Interfaces", "interfaces", NULL }, { "DisplayName", "display-name", NULL }, { "Icon", "icon", NULL }, - { "Valid", "valid", NULL }, + { "Usable", "usable", NULL }, { "Enabled", "enabled", NULL }, { "Nickname", "nickname", NULL }, { "Parameters", "parameters", NULL }, @@ -375,11 +389,11 @@ tp_tests_simple_account_class_init (TpTestsSimpleAccountClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ICON, param_spec); - param_spec = g_param_spec_boolean ("valid", "valid", - "Valid property", + param_spec = g_param_spec_boolean ("usable", "usable", + "Usable property", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_VALID, param_spec); + g_object_class_install_property (object_class, PROP_USABLE, param_spec); param_spec = g_param_spec_boolean ("enabled", "enabled", "Enabled property", @@ -401,7 +415,7 @@ tp_tests_simple_account_class_init (TpTestsSimpleAccountClass *klass) param_spec = g_param_spec_boxed ("automatic-presence", "automatic presence", "AutomaticPresence property", - TP_STRUCT_TYPE_SIMPLE_PRESENCE, + TP_STRUCT_TYPE_PRESENCE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_AUTOMATIC_PRESENCE, param_spec); @@ -435,14 +449,14 @@ tp_tests_simple_account_class_init (TpTestsSimpleAccountClass *klass) param_spec = g_param_spec_boxed ("current-presence", "current presence", "CurrentPresence property", - TP_STRUCT_TYPE_SIMPLE_PRESENCE, + TP_STRUCT_TYPE_PRESENCE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CURRENT_PRESENCE, param_spec); param_spec = g_param_spec_boxed ("requested-presence", "requested presence", "RequestedPresence property", - TP_STRUCT_TYPE_SIMPLE_PRESENCE, + TP_STRUCT_TYPE_PRESENCE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_REQUESTED_PRESENCE, param_spec); @@ -533,12 +547,12 @@ tp_tests_simple_account_set_presence (TpTestsSimpleAccount *self, g_object_get (self, "current-presence", &v, NULL); props = tp_asv_new ( - "CurrentPresence", TP_STRUCT_TYPE_SIMPLE_PRESENCE, v, + "CurrentPresence", TP_STRUCT_TYPE_PRESENCE, v, NULL); tp_svc_account_emit_account_property_changed (self, props); - g_boxed_free (TP_STRUCT_TYPE_SIMPLE_PRESENCE, v); + g_boxed_free (TP_STRUCT_TYPE_PRESENCE, v); } void @@ -578,3 +592,25 @@ tp_tests_simple_account_set_enabled (TpTestsSimpleAccount *self, tp_svc_account_emit_account_property_changed (self, change); g_hash_table_unref (change); } + +void +tp_tests_simple_account_add_uri_scheme (TpTestsSimpleAccount *self, + const gchar *uri_scheme) +{ + GHashTable *changed; + GStrv schemes; + + g_ptr_array_add (self->priv->uri_schemes, g_strdup (uri_scheme)); + + g_object_get (self, "uri-schemes", &schemes, NULL); + + changed = tp_asv_new ( + "URISchemes", G_TYPE_STRV, schemes, + NULL); + + tp_svc_dbus_properties_emit_properties_changed (self, + TP_IFACE_ACCOUNT_INTERFACE_ADDRESSING, changed, NULL); + + g_strfreev (schemes); + g_hash_table_unref (changed); +} diff --git a/tests/lib/telepathy/contactlist/simple-account.h b/tests/lib/telepathy/contactlist/simple-account.h index 2ce3efd1..351c6cc2 100644 --- a/tests/lib/telepathy/contactlist/simple-account.h +++ b/tests/lib/telepathy/contactlist/simple-account.h @@ -13,8 +13,7 @@ #include <glib-object.h> -#include <telepathy-glib/connection.h> -#include <telepathy-glib/dbus-properties-mixin.h> +#include <telepathy-glib/telepathy-glib.h> G_BEGIN_DECLS @@ -64,6 +63,9 @@ void tp_tests_simple_account_removed (TpTestsSimpleAccount *self); void tp_tests_simple_account_set_enabled (TpTestsSimpleAccount *self, gboolean enabled); +void tp_tests_simple_account_add_uri_scheme (TpTestsSimpleAccount *self, + const gchar * uri_scheme); + G_END_DECLS #endif /* #ifndef __TP_TESTS_SIMPLE_ACCOUNT_H__ */ diff --git a/tests/lib/telepathy/contactlist/simple-channel-dispatch-operation.c b/tests/lib/telepathy/contactlist/simple-channel-dispatch-operation.c new file mode 100644 index 00000000..82b38197 --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-channel-dispatch-operation.c @@ -0,0 +1,303 @@ +/* + * simple-channel-dispatch-operation.c - a simple channel dispatch operation + * service. + * + * Copyright Ā© 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "simple-channel-dispatch-operation.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +static void channel_dispatch_operation_iface_init (gpointer, gpointer); + +G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleChannelDispatchOperation, + tp_tests_simple_channel_dispatch_operation, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_DISPATCH_OPERATION, + channel_dispatch_operation_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init) + ) + +/* TP_IFACE_CHANNEL_DISPATCH_OPERATION is implied */ +static const char *CHANNEL_DISPATCH_OPERATION_INTERFACES[] = { NULL }; + +static const gchar *CHANNEL_DISPATCH_OPERATION_POSSIBLE_HANDLERS[] = { + TP_CLIENT_BUS_NAME_BASE ".Badger", NULL, }; + +enum +{ + PROP_0, + PROP_INTERFACES, + PROP_CONNECTION, + PROP_ACCOUNT, + PROP_CHANNELS, + PROP_POSSIBLE_HANDLERS, +}; + +struct _SimpleChannelDispatchOperationPrivate +{ + gchar *conn_path; + gchar *account_path; + /* Array of TpChannel */ + GPtrArray *channels; +}; + +static void +tp_tests_simple_channel_dispatch_operation_handle_with ( + TpSvcChannelDispatchOperation *iface, + const gchar *handler, + DBusGMethodInvocation *context) +{ + if (!tp_strdiff (handler, "FAIL")) + { + GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Nope" }; + + dbus_g_method_return_error (context, &error); + return; + } + + dbus_g_method_return (context); +} + +static void +tp_tests_simple_channel_dispatch_operation_claim ( + TpSvcChannelDispatchOperation *iface, + DBusGMethodInvocation *context) +{ + tp_svc_channel_dispatch_operation_emit_finished (iface); + + dbus_g_method_return (context); +} + +static void +tp_tests_simple_channel_dispatch_operation_handle_with_time ( + TpSvcChannelDispatchOperation *iface, + const gchar *handler, + gint64 user_action_timestamp, + DBusGMethodInvocation *context) +{ + dbus_g_method_return (context); +} + +static void +channel_dispatch_operation_iface_init (gpointer klass, + gpointer unused G_GNUC_UNUSED) +{ +#define IMPLEMENT(x) tp_svc_channel_dispatch_operation_implement_##x (\ + klass, tp_tests_simple_channel_dispatch_operation_##x) + IMPLEMENT(handle_with); + IMPLEMENT(claim); + IMPLEMENT(handle_with_time); +#undef IMPLEMENT +} + + +static void +tp_tests_simple_channel_dispatch_operation_init (TpTestsSimpleChannelDispatchOperation *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCH_OPERATION, + TpTestsSimpleChannelDispatchOperationPrivate); + + self->priv->channels = g_ptr_array_new_with_free_func ( + (GDestroyNotify) g_object_unref); +} + +static void +tp_tests_simple_channel_dispatch_operation_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *spec) +{ + TpTestsSimpleChannelDispatchOperation *self = + TP_TESTS_SIMPLE_CHANNEL_DISPATCH_OPERATION (object); + + switch (property_id) { + case PROP_INTERFACES: + g_value_set_boxed (value, CHANNEL_DISPATCH_OPERATION_INTERFACES); + break; + + case PROP_ACCOUNT: + g_value_set_boxed (value, self->priv->account_path); + break; + + case PROP_CONNECTION: + g_value_set_boxed (value, self->priv->conn_path); + break; + + case PROP_CHANNELS: + { + GPtrArray *arr = g_ptr_array_new (); + guint i; + + for (i = 0; i < self->priv->channels->len; i++) + { + TpChannel *channel = g_ptr_array_index (self->priv->channels, i); + GValue props_value = G_VALUE_INIT; + GVariant *props_variant; + + /* Yay, double conversion! But this is for tests corner case */ + props_variant = tp_channel_dup_immutable_properties (channel); + dbus_g_value_parse_g_variant (props_variant, &props_value); + + g_ptr_array_add (arr, + tp_value_array_build (2, + DBUS_TYPE_G_OBJECT_PATH, tp_proxy_get_object_path (channel), + TP_HASH_TYPE_STRING_VARIANT_MAP, + g_value_get_boxed (&props_value), + G_TYPE_INVALID)); + + g_variant_unref (props_variant); + g_value_unset (&props_value); + } + + g_value_take_boxed (value, arr); + } + break; + + case PROP_POSSIBLE_HANDLERS: + g_value_set_boxed (value, CHANNEL_DISPATCH_OPERATION_POSSIBLE_HANDLERS); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); + break; + } +} + +static void +tp_tests_simple_channel_dispatch_operation_finalize (GObject *object) +{ + TpTestsSimpleChannelDispatchOperation *self = + TP_TESTS_SIMPLE_CHANNEL_DISPATCH_OPERATION (object); + void (*finalize) (GObject *) = + G_OBJECT_CLASS (tp_tests_simple_channel_dispatch_operation_parent_class)->finalize; + + g_free (self->priv->conn_path); + g_free (self->priv->account_path); + g_ptr_array_unref (self->priv->channels); + + if (finalize != NULL) + finalize (object); +} + +/** + * This class currently only provides the minimum for + * tp_channel_dispatch_operation_prepare to succeed. This turns out to be only a working + * Properties.GetAll(). + */ +static void +tp_tests_simple_channel_dispatch_operation_class_init (TpTestsSimpleChannelDispatchOperationClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + GParamSpec *param_spec; + + static TpDBusPropertiesMixinPropImpl a_props[] = { + { "Interfaces", "interfaces", NULL }, + { "Connection", "connection", NULL }, + { "Account", "account", NULL }, + { "Channels", "channels", NULL }, + { "PossibleHandlers", "possible-handlers", NULL }, + { NULL } + }; + + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { TP_IFACE_CHANNEL_DISPATCH_OPERATION, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + a_props + }, + { NULL }, + }; + + g_type_class_add_private (klass, sizeof (TpTestsSimpleChannelDispatchOperationPrivate)); + object_class->get_property = tp_tests_simple_channel_dispatch_operation_get_property; + object_class->finalize = tp_tests_simple_channel_dispatch_operation_finalize; + + param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces", + "In this case we only implement ChannelDispatchOperation, so none.", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); + + param_spec = g_param_spec_boxed ("connection", "connection path", + "Connection path", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); + + param_spec = g_param_spec_boxed ("account", "account path", + "Account path", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec); + + param_spec = g_param_spec_boxed ("channels", "channel paths", + "Channel paths", + TP_ARRAY_TYPE_CHANNEL_DETAILS_LIST, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_CHANNELS, param_spec); + + param_spec = g_param_spec_boxed ("possible-handlers", "possible handlers", + "possible handles", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_POSSIBLE_HANDLERS, + param_spec); + + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (TpTestsSimpleChannelDispatchOperationClass, dbus_props_class)); +} + +void +tp_tests_simple_channel_dispatch_operation_set_conn_path ( + TpTestsSimpleChannelDispatchOperation *self, + const gchar *conn_path) +{ + self->priv->conn_path = g_strdup (conn_path); +} + +void +tp_tests_simple_channel_dispatch_operation_add_channel ( + TpTestsSimpleChannelDispatchOperation *self, + TpChannel *chan) +{ + g_ptr_array_add (self->priv->channels, g_object_ref (chan)); +} + +void +tp_tests_simple_channel_dispatch_operation_lost_channel ( + TpTestsSimpleChannelDispatchOperation *self, + TpChannel *chan) +{ + const gchar *path = tp_proxy_get_object_path (chan); + + g_ptr_array_remove (self->priv->channels, chan); + + tp_svc_channel_dispatch_operation_emit_channel_lost (self, path, + TP_ERROR_STR_NOT_AVAILABLE, "Badger"); + + if (self->priv->channels->len == 0) + { + /* We removed the last channel; fire Finished */ + tp_svc_channel_dispatch_operation_emit_finished (self); + } +} + +void +tp_tests_simple_channel_dispatch_operation_set_account_path ( + TpTestsSimpleChannelDispatchOperation *self, + const gchar *account_path) +{ + self->priv->account_path = g_strdup (account_path); +} diff --git a/tests/lib/telepathy/contactlist/simple-channel-dispatch-operation.h b/tests/lib/telepathy/contactlist/simple-channel-dispatch-operation.h new file mode 100644 index 00000000..3e9ee934 --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-channel-dispatch-operation.h @@ -0,0 +1,73 @@ +/* + * simple-channel-dispatch-operation.h - a simple channel dispatch operation + * service. + * + * Copyright Ā© 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_SIMPLE_CHANNEL_DISPATCH_OPERATION_H__ +#define __TP_TESTS_SIMPLE_CHANNEL_DISPATCH_OPERATION_H__ + +#include <glib-object.h> + +#include <telepathy-glib/telepathy-glib.h> + +G_BEGIN_DECLS + +typedef struct _SimpleChannelDispatchOperation TpTestsSimpleChannelDispatchOperation; +typedef struct _SimpleChannelDispatchOperationClass TpTestsSimpleChannelDispatchOperationClass; +typedef struct _SimpleChannelDispatchOperationPrivate TpTestsSimpleChannelDispatchOperationPrivate; + +struct _SimpleChannelDispatchOperationClass { + GObjectClass parent_class; + TpDBusPropertiesMixinClass dbus_props_class; +}; + +struct _SimpleChannelDispatchOperation { + GObject parent; + + TpTestsSimpleChannelDispatchOperationPrivate *priv; +}; + +GType tp_tests_simple_channel_dispatch_operation_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCH_OPERATION \ + (tp_tests_simple_channel_dispatch_operation_get_type ()) +#define TP_TESTS_SIMPLE_CHANNEL_DISPATCH_OPERATION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCH_OPERATION, \ + TpTestsSimpleChannelDispatchOperation)) +#define TP_TESTS_SIMPLE_CHANNEL_DISPATCH_OPERATION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCH_OPERATION, \ + TpTestsSimpleChannelDispatchOperationClass)) +#define SIMPLE_IS_CHANNEL_DISPATCH_OPERATION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCH_OPERATION)) +#define SIMPLE_IS_CHANNEL_DISPATCH_OPERATION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCH_OPERATION)) +#define TP_TESTS_SIMPLE_CHANNEL_DISPATCH_OPERATION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCH_OPERATION, \ + TpTestsSimpleChannelDispatchOperationClass)) + +void tp_tests_simple_channel_dispatch_operation_set_conn_path ( + TpTestsSimpleChannelDispatchOperation *self, + const gchar *conn_path); + +void tp_tests_simple_channel_dispatch_operation_add_channel ( + TpTestsSimpleChannelDispatchOperation *self, + TpChannel *chan); + +void tp_tests_simple_channel_dispatch_operation_lost_channel ( + TpTestsSimpleChannelDispatchOperation *self, + TpChannel *chan); + +void tp_tests_simple_channel_dispatch_operation_set_account_path ( + TpTestsSimpleChannelDispatchOperation *self, + const gchar *account_path); + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_SIMPLE_CHANNEL_DISPATCH_OPERATION_H__ */ diff --git a/tests/lib/telepathy/contactlist/simple-channel-dispatcher.c b/tests/lib/telepathy/contactlist/simple-channel-dispatcher.c new file mode 100644 index 00000000..775f915e --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-channel-dispatcher.c @@ -0,0 +1,394 @@ +/* + * simple-channel-dispatcher.c - simple channel dispatcher service. + * + * Copyright Ā© 2010 Collabora Ltd. + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "simple-channel-dispatcher.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +#include "simple-channel-request.h" +#include "simple-conn.h" + +static void channel_dispatcher_iface_init (gpointer, gpointer); + +G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleChannelDispatcher, + tp_tests_simple_channel_dispatcher, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_DISPATCHER, + channel_dispatcher_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init) + ) + +/* signals */ +enum { + CHANNEL_REQUEST_CREATED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +/* TP_IFACE_CHANNEL_DISPATCHER is implied */ +static const char *CHANNEL_DISPATCHER_INTERFACES[] = { NULL }; + +enum +{ + PROP_0, + PROP_INTERFACES, + PROP_CONNECTION, +}; + +struct _TpTestsSimpleChannelDispatcherPrivate +{ + /* To keep things simpler, this CD can only create channels using one + * connection */ + TpTestsSimpleConnection *conn; + + /* List of reffed TpTestsSimpleChannelRequest */ + GSList *requests; + + /* Used when ensuring a channel to store its handler. + * If this is set we fake that the channel already exist and re-call + * HandleChannels() on the handler rather than creating a new channel. + * This is pretty stupid but good enough for our tests. */ + gchar *old_handler; +}; + +static gchar * +create_channel_request (TpTestsSimpleChannelDispatcher *self, + const gchar *account, + GHashTable *request, + gint64 user_action_time, + const gchar *preferred_handler, + GHashTable *hints_, + GHashTable **out_immutable_properties) +{ + TpTestsSimpleChannelRequest *chan_request; + GPtrArray *requests; + static guint count = 0; + gchar *path; + TpDBusDaemon *dbus; + GHashTable *hints; + + requests = g_ptr_array_sized_new (1); + g_ptr_array_add (requests, request); + + path = g_strdup_printf ("/Request%u", count++); + + if (hints_ == NULL) + hints = g_hash_table_new (NULL, NULL); + else + hints = g_hash_table_ref (hints_); + + chan_request = tp_tests_simple_channel_request_new (path, + self->priv->conn, account, user_action_time, preferred_handler, requests, + hints); + + g_hash_table_unref (hints); + + self->priv->requests = g_slist_append (self->priv->requests, chan_request); + + g_ptr_array_unref (requests); + + dbus = tp_dbus_daemon_dup (NULL); + g_assert (dbus != NULL); + + tp_dbus_daemon_register_object (dbus, path, chan_request); + + g_object_unref (dbus); + + g_signal_emit (self, signals[CHANNEL_REQUEST_CREATED], 0, chan_request); + + *out_immutable_properties = + tp_tests_simple_channel_request_dup_immutable_props (chan_request); + + return path; +} + +static void +tp_tests_simple_channel_dispatcher_create_channel ( + TpSvcChannelDispatcher *dispatcher, + const gchar *account, + GHashTable *request, + gint64 user_action_time, + const gchar *preferred_handler, + GHashTable *hints, + DBusGMethodInvocation *context) +{ + TpTestsSimpleChannelDispatcher *self = SIMPLE_CHANNEL_DISPATCHER (dispatcher); + gchar *path; + GHashTable *immutable_properties; + + tp_clear_pointer (&self->last_request, g_hash_table_unref); + self->last_request = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP, request); + tp_clear_pointer (&self->last_hints, g_hash_table_unref); + self->last_hints = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP, request); + self->last_user_action_time = user_action_time; + g_free (self->last_account); + self->last_account = g_strdup (account); + g_free (self->last_preferred_handler); + self->last_preferred_handler = g_strdup (preferred_handler); + + if (tp_asv_get_boolean (request, "CreateChannelFail", NULL)) + { + /* Fail to create the channel */ + GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Computer says no" }; + + dbus_g_method_return_error (context, &error); + return; + } + + path = create_channel_request (self, account, request, user_action_time, + preferred_handler, hints, &immutable_properties); + + if (path == NULL) + return; + + tp_svc_channel_dispatcher_return_from_create_channel (context, + path, immutable_properties); + + g_free (path); + g_hash_table_unref (immutable_properties); +} + +static void +tp_tests_simple_channel_dispatcher_ensure_channel ( + TpSvcChannelDispatcher *dispatcher, + const gchar *account, + GHashTable *request, + gint64 user_action_time, + const gchar *preferred_handler, + GHashTable *hints, + DBusGMethodInvocation *context) +{ + TpTestsSimpleChannelDispatcher *self = SIMPLE_CHANNEL_DISPATCHER (dispatcher); + gchar *path; + GHashTable *immutable_properties; + + tp_clear_pointer (&self->last_request, g_hash_table_unref); + self->last_request = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP, request); + tp_clear_pointer (&self->last_hints, g_hash_table_unref); + self->last_hints = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP, request); + self->last_user_action_time = user_action_time; + g_free (self->last_account); + self->last_account = g_strdup (account); + g_free (self->last_preferred_handler); + self->last_preferred_handler = g_strdup (preferred_handler); + + if (self->priv->old_handler != NULL) + { + /* Pretend that the channel already exists */ + path = create_channel_request (self, account, request, user_action_time, + self->priv->old_handler, hints, &immutable_properties); + } + else + { + self->priv->old_handler = g_strdup (preferred_handler); + + path = create_channel_request (self, account, request, user_action_time, + preferred_handler, hints, &immutable_properties); + } + + tp_svc_channel_dispatcher_return_from_ensure_channel (context, + path, immutable_properties); + + g_free (path); + g_hash_table_unref (immutable_properties); +} + +static void +free_not_delegated_error (gpointer data) +{ + g_boxed_free (TP_STRUCT_TYPE_NOT_DELEGATED_ERROR, data); +} + + +static void +tp_tests_simple_channel_dispatcher_delegate_channels ( + TpSvcChannelDispatcher *dispatcher, + const GPtrArray *channels, + gint64 user_action_time, + const gchar *preferred_handler, + DBusGMethodInvocation *context) +{ + TpTestsSimpleChannelDispatcher *self = (TpTestsSimpleChannelDispatcher *) + dispatcher; + GPtrArray *delegated; + GHashTable *not_delegated; + guint i; + + delegated = g_ptr_array_new (); + not_delegated = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, free_not_delegated_error); + + for (i = 0; i < channels->len; i++) + { + gpointer chan_path = g_ptr_array_index (channels, i); + GValueArray *v; + + if (!self->refuse_delegate) + { + g_ptr_array_add (delegated, chan_path); + continue; + } + + v = tp_value_array_build (2, + G_TYPE_STRING, TP_ERROR_STR_BUSY, + G_TYPE_STRING, "Nah!", + G_TYPE_INVALID); + + g_hash_table_insert (not_delegated, chan_path, v); + } + + tp_svc_channel_dispatcher_return_from_delegate_channels (context, delegated, + not_delegated); + + g_ptr_array_unref (delegated); + g_hash_table_unref (not_delegated); +} + +static void +tp_tests_simple_channel_dispatcher_present_channel ( + TpSvcChannelDispatcher *dispatcher, + const gchar *channel, + gint64 user_action_time, + DBusGMethodInvocation *context) +{ + tp_svc_channel_dispatcher_return_from_present_channel (context); +} + +static void +channel_dispatcher_iface_init (gpointer klass, + gpointer unused G_GNUC_UNUSED) +{ +#define IMPLEMENT(x) tp_svc_channel_dispatcher_implement_##x (\ + klass, tp_tests_simple_channel_dispatcher_##x) + IMPLEMENT (create_channel); + IMPLEMENT (ensure_channel); + IMPLEMENT (delegate_channels); + IMPLEMENT (present_channel); +#undef IMPLEMENT +} + + +static void +tp_tests_simple_channel_dispatcher_init (TpTestsSimpleChannelDispatcher *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER, + TpTestsSimpleChannelDispatcherPrivate); +} + +static void +tp_tests_simple_channel_dispatcher_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *spec) +{ + switch (property_id) { + case PROP_INTERFACES: + g_value_set_boxed (value, CHANNEL_DISPATCHER_INTERFACES); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); + break; + } +} + +static void +tp_tests_simple_channel_dispatcher_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *spec) +{ + TpTestsSimpleChannelDispatcher *self = SIMPLE_CHANNEL_DISPATCHER (object); + + switch (property_id) { + case PROP_CONNECTION: + self->priv->conn = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); + break; + } +} + +static void +tp_tests_simple_channel_dispatcher_dispose (GObject *object) +{ + TpTestsSimpleChannelDispatcher *self = SIMPLE_CHANNEL_DISPATCHER (object); + + tp_clear_object (&self->priv->conn); + + g_slist_foreach (self->priv->requests, (GFunc) g_object_unref, NULL); + g_slist_free (self->priv->requests); + + g_free (self->priv->old_handler); + + if (G_OBJECT_CLASS (tp_tests_simple_channel_dispatcher_parent_class)->dispose != NULL) + G_OBJECT_CLASS (tp_tests_simple_channel_dispatcher_parent_class)->dispose (object); +} + +static void +tp_tests_simple_channel_dispatcher_class_init ( + TpTestsSimpleChannelDispatcherClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + GParamSpec *param_spec; + + static TpDBusPropertiesMixinPropImpl am_props[] = { + { "Interfaces", "interfaces", NULL }, + { NULL } + }; + + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { TP_IFACE_CHANNEL_DISPATCHER, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + am_props + }, + { NULL }, + }; + + g_type_class_add_private (klass, sizeof (TpTestsSimpleChannelDispatcherPrivate)); + object_class->get_property = tp_tests_simple_channel_dispatcher_get_property; + object_class->set_property = tp_tests_simple_channel_dispatcher_set_property; + + object_class->dispose = tp_tests_simple_channel_dispatcher_dispose; + + param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces", + "In this case we only implement ChannelDispatcher, so none.", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); + + param_spec = g_param_spec_object ("connection", "TpTestsSimpleConnection", + "connection to use when creating channels", + TP_TESTS_TYPE_SIMPLE_CONNECTION, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); + + /* Fired when we create a new channel request object. This can be used in + * test to track the progression of a request. */ + signals[CHANNEL_REQUEST_CREATED] = g_signal_new ("channel-request-created", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 1, TP_TESTS_TYPE_SIMPLE_CHANNEL_REQUEST); + + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (TpTestsSimpleChannelDispatcherClass, dbus_props_class)); +} diff --git a/tests/lib/telepathy/contactlist/simple-channel-dispatcher.h b/tests/lib/telepathy/contactlist/simple-channel-dispatcher.h new file mode 100644 index 00000000..da214061 --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-channel-dispatcher.h @@ -0,0 +1,66 @@ +/* + * simple-channel-dispatcher.h - header for a simple channel dispatcher service. + * + * Copyright Ā© 2010 Collabora Ltd. + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_SIMPLE_CHANNEL_DISPATCHER_H__ +#define __TP_TESTS_SIMPLE_CHANNEL_DISPATCHER_H__ + +#include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + + +G_BEGIN_DECLS + +typedef struct _TpTestsSimpleChannelDispatcher TpTestsSimpleChannelDispatcher; +typedef struct _TpTestsSimpleChannelDispatcherClass TpTestsSimpleChannelDispatcherClass; +typedef struct _TpTestsSimpleChannelDispatcherPrivate TpTestsSimpleChannelDispatcherPrivate; + +struct _TpTestsSimpleChannelDispatcherClass { + GObjectClass parent_class; + TpDBusPropertiesMixinClass dbus_props_class; +}; + +struct _TpTestsSimpleChannelDispatcher { + GObject parent; + + /* so regression tests can verify what was asked for */ + GHashTable *last_request; + gchar *last_account; + gint64 last_user_action_time; + gchar *last_preferred_handler; + GHashTable *last_hints; + + TpTestsSimpleChannelDispatcherPrivate *priv; + + gboolean refuse_delegate; +}; + +GType tp_tests_simple_channel_dispatcher_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER \ + (tp_tests_simple_channel_dispatcher_get_type ()) +#define SIMPLE_CHANNEL_DISPATCHER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER, \ + TpTestsSimpleChannelDispatcher)) +#define SIMPLE_CHANNEL_DISPATCHER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER, \ + TpTestsSimpleChannelDispatcherClass)) +#define SIMPLE_IS_CHANNEL_DISPATCHER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER)) +#define SIMPLE_IS_CHANNEL_DISPATCHER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER)) +#define SIMPLE_CHANNEL_DISPATCHER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER, \ + TpTestsSimpleChannelDispatcherClass)) + + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_SIMPLE_CHANNEL_DISPATCHER_H__ */ diff --git a/tests/lib/telepathy/contactlist/simple-channel-manager.c b/tests/lib/telepathy/contactlist/simple-channel-manager.c new file mode 100644 index 00000000..ba60a9d9 --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-channel-manager.c @@ -0,0 +1,95 @@ +/* + * simple-channel-manager.c + * + * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +#include "simple-channel-manager.h" +#include "util.h" +#include "echo-chan.h" + +static void channel_manager_iface_init (gpointer, gpointer); + +G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleChannelManager, + tp_tests_simple_channel_manager, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); + ) + +/* signals */ +enum { + REQUEST, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +tp_tests_simple_channel_manager_class_init (TpTestsSimpleChannelManagerClass *klass) +{ + signals[REQUEST] = g_signal_new ("request", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_HASH_TABLE); +} + +static void +tp_tests_simple_channel_manager_init (TpTestsSimpleChannelManager *self) +{ +} + +static gboolean +tp_tests_simple_channel_manager_request (TpChannelManager *manager, + gpointer request_token, + GHashTable *request_properties) +{ + TpTestsSimpleChannelManager *self = + TP_TESTS_SIMPLE_CHANNEL_MANAGER (manager); + GSList *tokens; + TpExportableChannel *channel; + TpHandle handle = tp_asv_get_uint32 (request_properties, + TP_PROP_CHANNEL_TARGET_HANDLE, NULL); + gchar *path; + + g_signal_emit (manager, signals[REQUEST], 0, request_properties); + + tokens = g_slist_append (NULL, request_token); + + path = g_strdup_printf ("%s/Channel", + tp_base_connection_get_object_path (self->conn)); + + channel = tp_tests_object_new_static_class ( + TP_TESTS_TYPE_ECHO_CHANNEL, + "connection", self->conn, + "object-path", path, + "handle", handle, + NULL); + + tp_channel_manager_emit_new_channel (manager, channel, tokens); + + g_free (path); + g_slist_free (tokens); + g_object_unref (channel); + + return TRUE; +} + +static void +channel_manager_iface_init (gpointer g_iface, + gpointer giface_data G_GNUC_UNUSED) +{ + TpChannelManagerIface *iface = g_iface; + + iface->create_channel = tp_tests_simple_channel_manager_request; + iface->ensure_channel = tp_tests_simple_channel_manager_request; + iface->request_channel = tp_tests_simple_channel_manager_request; +} diff --git a/tests/lib/telepathy/contactlist/simple-channel-manager.h b/tests/lib/telepathy/contactlist/simple-channel-manager.h new file mode 100644 index 00000000..ad711cd5 --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-channel-manager.h @@ -0,0 +1,54 @@ +/* + * simple-channel-manager.h + * + * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_SIMPLE_CHANNEL_MANAGER_H__ +#define __TP_TESTS_SIMPLE_CHANNEL_MANAGER_H__ + +#include <glib-object.h> + +#include <telepathy-glib/telepathy-glib.h> + +typedef struct _TpTestsSimpleChannelManager TpTestsSimpleChannelManager; +typedef struct _TpTestsSimpleChannelManagerClass TpTestsSimpleChannelManagerClass; + +struct _TpTestsSimpleChannelManager +{ + GObject parent; + + TpBaseConnection *conn; +}; + +struct _TpTestsSimpleChannelManagerClass +{ + GObjectClass parent_class; +}; + +GType tp_tests_simple_channel_manager_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_SIMPLE_CHANNEL_MANAGER \ + (tp_tests_simple_channel_manager_get_type ()) +#define TP_TESTS_SIMPLE_CHANNEL_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_MANAGER, \ + TpTestsSimpleChannelManager)) +#define TP_TESTS_SIMPLE_CHANNEL_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_SIMPLE_CHANNEL_MANAGER, \ + TpTestsSimpleChannelManagerClass)) +#define TP_TESTS_IS_SIMPLE_CHANNEL_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_MANAGER)) +#define TP_TESTS_IS_SIMPLE_CHANNEL_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_SIMPLE_CHANNEL_MANAGER)) +#define TP_TESTS_SIMPLE_CHANNEL_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_MANAGER, \ + TpTestsSimpleChannelManagerClass)) + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_SIMPLE_CHANNEL_MANAGER_H__ */ diff --git a/tests/lib/telepathy/contactlist/simple-channel-request.c b/tests/lib/telepathy/contactlist/simple-channel-request.c new file mode 100644 index 00000000..4884cb02 --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-channel-request.c @@ -0,0 +1,508 @@ +/* + * simple-channel-request.c - simple channel request service. + * + * Copyright Ā© 2010 Collabora Ltd. + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "simple-channel-request.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> +#include <telepathy-glib/proxy-subclass.h> + +#include "tests/lib/util.h" + +static void channel_request_iface_init (gpointer, gpointer); + +G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleChannelRequest, + tp_tests_simple_channel_request, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_REQUEST, + channel_request_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init) + ) + + +/* TP_IFACE_CHANNEL_REQUEST is implied */ +static const char *CHANNEL_REQUEST_INTERFACES[] = { NULL }; + +enum +{ + PROP_0, + PROP_PATH, + PROP_ACCOUNT, + PROP_USER_ACTION_TIME, + PROP_PREFERRED_HANDLER, + PROP_REQUESTS, + PROP_CONNECTION, + PROP_INTERFACES, + PROP_HINTS, +}; + +struct _TpTestsSimpleChannelRequestPrivate +{ + /* D-Bus properties */ + gchar *account_path; + gint64 user_action_time; + gchar *preferred_handler; + GPtrArray *requests; + GHashTable *hints; + + /* Our own path */ + gchar *path; + + /* connection used to create channels */ + TpTestsSimpleConnection *conn; +}; + +static void +handle_channels_cb (TpClient *client, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + TpTestsSimpleChannelRequest *self = SIMPLE_CHANNEL_REQUEST (weak_object); + TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->conn); + const gchar *chan_path = user_data; + GHashTable *props = tp_asv_new (NULL, NULL); + + if (error != NULL) + { + tp_svc_channel_request_emit_failed (self, + tp_error_get_dbus_name (error->code), error->message); + return; + } + + tp_svc_channel_request_emit_succeeded (self, + tp_base_connection_get_object_path (base_conn), props, chan_path, props); + + g_hash_table_unref (props); +} + +static gchar * +add_channel (TpTestsSimpleChannelRequest *self, + GPtrArray *channels) +{ + const gchar *target_id; + gchar *chan_path; + GHashTable *request; + GHashTable *props; + const char *chan_type; + + request = g_ptr_array_index (self->priv->requests, 0); + chan_type = tp_asv_get_string (request, TP_PROP_CHANNEL_CHANNEL_TYPE); + + if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_TEXT)) + { + target_id = tp_asv_get_string (request, TP_PROP_CHANNEL_TARGET_ID); + g_assert (target_id != NULL); + + chan_path = tp_tests_simple_connection_ensure_text_chan (self->priv->conn, + target_id, &props); + } + else if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_ROOM_LIST)) + { + chan_path = tp_tests_simple_connection_ensure_room_list_chan ( + self->priv->conn, tp_asv_get_string (request, + TP_PROP_CHANNEL_TYPE_ROOM_LIST_SERVER), &props); + } + else + { + g_assert_not_reached (); + } + + g_ptr_array_add (channels, tp_value_array_build (2, + DBUS_TYPE_G_OBJECT_PATH, chan_path, + TP_HASH_TYPE_STRING_VARIANT_MAP, props, + G_TYPE_INVALID)); + + g_hash_table_unref (props); + + return chan_path; +} + +static void +free_channel_details (gpointer data, + gpointer user_data) +{ + g_boxed_free (TP_STRUCT_TYPE_CHANNEL_DETAILS, data); +} + +GHashTable * +tp_tests_simple_channel_request_dup_immutable_props ( + TpTestsSimpleChannelRequest *self) +{ + return tp_asv_new ( + TP_PROP_CHANNEL_REQUEST_ACCOUNT, DBUS_TYPE_G_OBJECT_PATH, + self->priv->account_path, + TP_PROP_CHANNEL_REQUEST_USER_ACTION_TIME, G_TYPE_INT64, + self->priv->user_action_time, + TP_PROP_CHANNEL_REQUEST_PREFERRED_HANDLER, G_TYPE_STRING, + self->priv->preferred_handler, + TP_PROP_CHANNEL_REQUEST_REQUESTS, TP_ARRAY_TYPE_CHANNEL_CLASS_LIST, + self->priv->requests, + TP_PROP_CHANNEL_REQUEST_INTERFACES, G_TYPE_STRV, NULL, + TP_PROP_CHANNEL_REQUEST_HINTS, TP_HASH_TYPE_STRING_VARIANT_MAP, + self->priv->hints, + NULL); +} + +static void +tp_tests_simple_channel_request_proceed (TpSvcChannelRequest *request, + DBusGMethodInvocation *context) +{ + TpTestsSimpleChannelRequest *self = SIMPLE_CHANNEL_REQUEST (request); + TpClient *client; + TpDBusDaemon *dbus; + gchar *client_path; + GPtrArray *channels; + GPtrArray *satisfied; + GHashTable *info; + TpBaseConnection *base_conn = (TpBaseConnection *) self->priv->conn; + GHashTable *req; + GHashTable *request_props; + gchar *chan_path; + + req = g_ptr_array_index (self->priv->requests, 0); + g_assert (req != NULL); + if (tp_asv_get_boolean (req, "ProceedFail", NULL)) + { + /* We have been asked to fail */ + GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Computer says no" }; + + dbus_g_method_return_error (context, &error); + return; + } + + tp_svc_channel_request_return_from_proceed (context); + + if (tp_asv_get_boolean (req, "FireFailed", NULL)) + { + /* We have been asked to fire the 'Failed' signal */ + tp_svc_channel_request_emit_failed (self, TP_ERROR_STR_INVALID_ARGUMENT, + "Let's fail!"); + return; + } + + /* We just support handling request having a preferred handler */ + if (self->priv->preferred_handler == NULL || + !tp_strdiff (self->priv->preferred_handler, "")) + { + tp_svc_channel_request_emit_failed (self, TP_ERROR_STR_NOT_AVAILABLE, + "ChannelRequest doesn't have a preferred handler"); + return; + } + + if (!tp_strdiff (self->priv->preferred_handler, "Fake")) + { + /* Pretend that the channel has been handled */ + GHashTable *props; + props = g_hash_table_new (NULL, NULL); + + tp_svc_channel_request_emit_succeeded (self, + tp_base_connection_get_object_path (base_conn), + props, "/chan", props); + + g_hash_table_unref (props); + return; + } + + /* Call HandleChannels() on the preferred handler */ + client_path = g_strdelimit (g_strdup_printf ("/%s", + self->priv->preferred_handler), ".", '/'); + + dbus = tp_dbus_daemon_dup (NULL); + g_assert (dbus != NULL); + + client = tp_tests_object_new_static_class (TP_TYPE_CLIENT, + "dbus-daemon", dbus, + "bus-name", self->priv->preferred_handler, + "object-path", client_path, + NULL); + + tp_proxy_add_interface_by_id (TP_PROXY (client), TP_IFACE_QUARK_CLIENT); + tp_proxy_add_interface_by_id (TP_PROXY (client), + TP_IFACE_QUARK_CLIENT_HANDLER); + + channels = g_ptr_array_sized_new (1); + chan_path = add_channel (self, channels); + + satisfied = g_ptr_array_sized_new (1); + g_ptr_array_add (satisfied, self->priv->path); + + request_props = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) g_hash_table_unref); + + g_hash_table_insert (request_props, g_strdup (self->priv->path), + tp_tests_simple_channel_request_dup_immutable_props (self)); + + info = tp_asv_new ( + "request-properties", TP_HASH_TYPE_OBJECT_IMMUTABLE_PROPERTIES_MAP, + request_props, + NULL); + + tp_cli_client_handler_call_handle_channels (client, -1, + self->priv->account_path, + tp_base_connection_get_object_path (base_conn), channels, + satisfied, self->priv->user_action_time, info, handle_channels_cb, + g_strdup (chan_path), g_free, G_OBJECT (self)); + + g_free (chan_path); + g_free (client_path); + g_ptr_array_foreach (channels, free_channel_details, NULL); + g_ptr_array_unref (channels); + g_ptr_array_unref (satisfied); + g_hash_table_unref (info); + g_hash_table_unref (request_props); + g_object_unref (dbus); + g_object_unref (client); +} + +static void +tp_tests_simple_channel_request_cancel (TpSvcChannelRequest *request, + DBusGMethodInvocation *context) +{ + tp_svc_channel_request_emit_failed (request, TP_ERROR_STR_CANCELLED, + "ChannelRequest has been cancelled"); + + tp_svc_channel_request_return_from_cancel (context); +} + +static void +channel_request_iface_init (gpointer klass, + gpointer unused G_GNUC_UNUSED) +{ +#define IMPLEMENT(x) tp_svc_channel_request_implement_##x (\ + klass, tp_tests_simple_channel_request_##x) + IMPLEMENT (proceed); + IMPLEMENT (cancel); +#undef IMPLEMENT +} + +static void +tp_tests_simple_channel_request_init (TpTestsSimpleChannelRequest *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + TP_TESTS_TYPE_SIMPLE_CHANNEL_REQUEST, + TpTestsSimpleChannelRequestPrivate); +} + +static void +tp_tests_simple_channel_request_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *spec) +{ + TpTestsSimpleChannelRequest *self = SIMPLE_CHANNEL_REQUEST (object); + + switch (property_id) { + case PROP_PATH: + g_value_set_string (value, self->priv->path); + break; + + case PROP_ACCOUNT: + g_value_set_string (value, self->priv->account_path); + break; + + case PROP_USER_ACTION_TIME: + g_value_set_int64 (value, self->priv->user_action_time); + break; + + case PROP_PREFERRED_HANDLER: + g_value_set_string (value, self->priv->preferred_handler); + break; + + case PROP_REQUESTS: + g_value_set_boxed (value, self->priv->requests); + break; + + case PROP_INTERFACES: + g_value_set_boxed (value, CHANNEL_REQUEST_INTERFACES); + break; + + case PROP_HINTS: + g_value_set_boxed (value, self->priv->hints); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); + break; + } +} + +static void +tp_tests_simple_channel_request_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *spec) +{ + TpTestsSimpleChannelRequest *self = SIMPLE_CHANNEL_REQUEST (object); + + switch (property_id) { + case PROP_PATH: + self->priv->path = g_value_dup_string (value); + break; + + case PROP_ACCOUNT: + self->priv->account_path = g_value_dup_string (value); + break; + + case PROP_USER_ACTION_TIME: + self->priv->user_action_time = g_value_get_int64 (value); + break; + + case PROP_PREFERRED_HANDLER: + self->priv->preferred_handler = g_value_dup_string (value); + break; + + case PROP_REQUESTS: + self->priv->requests = g_value_dup_boxed (value); + break; + + case PROP_CONNECTION: + self->priv->conn = g_value_dup_object (value); + break; + + case PROP_HINTS: + self->priv->hints = g_value_dup_boxed (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); + break; + } +} + +static void +tp_tests_simple_channel_request_dispose (GObject *object) +{ + TpTestsSimpleChannelRequest *self = SIMPLE_CHANNEL_REQUEST (object); + + g_free (self->priv->path); + g_free (self->priv->account_path); + g_free (self->priv->preferred_handler); + + if (self->priv->requests != NULL) + { + g_boxed_free (TP_ARRAY_TYPE_CHANNEL_CLASS_LIST, self->priv->requests); + self->priv->requests = NULL; + } + + tp_clear_object (&self->priv->conn); + tp_clear_pointer (&self->priv->hints, g_hash_table_unref); + + if (G_OBJECT_CLASS (tp_tests_simple_channel_request_parent_class)->dispose != NULL) + G_OBJECT_CLASS (tp_tests_simple_channel_request_parent_class)->dispose (object); +} + +static void +tp_tests_simple_channel_request_class_init ( + TpTestsSimpleChannelRequestClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + GParamSpec *param_spec; + + static TpDBusPropertiesMixinPropImpl am_props[] = { + { "Interfaces", "interfaces", NULL }, + { "Hints", "hints", NULL }, + { NULL } + }; + + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { TP_IFACE_CHANNEL_REQUEST, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + am_props + }, + { NULL }, + }; + + g_type_class_add_private (klass, sizeof (TpTestsSimpleChannelRequestPrivate)); + object_class->get_property = tp_tests_simple_channel_request_get_property; + object_class->set_property = tp_tests_simple_channel_request_set_property; + + object_class->dispose = tp_tests_simple_channel_request_dispose; + + param_spec = g_param_spec_string ("path", "Path", + "Path of this ChannelRequest", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_PATH, param_spec); + + param_spec = g_param_spec_string ("account", "Account", + "Path of the Account", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec); + + param_spec = g_param_spec_int64 ("user-action-time", "UserActionTime", + "UserActionTime", + G_MININT64, G_MAXINT64, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_USER_ACTION_TIME, + param_spec); + + param_spec = g_param_spec_string ("preferred-handler", "PreferredHandler", + "PreferredHandler", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_PREFERRED_HANDLER, + param_spec); + + param_spec = g_param_spec_boxed ("requests", "Requests", + "Requests", + TP_ARRAY_TYPE_CHANNEL_CLASS_LIST, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_REQUESTS, param_spec); + + param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces", + "In this case we only implement ChannelRequest, so none.", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); + + param_spec = g_param_spec_object ("connection", "TpBaseConnection", + "connection to use when creating channels", + TP_TYPE_BASE_CONNECTION, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); + + param_spec = g_param_spec_boxed ("hints", "Hints", + "Metadata provided by the channel's requester, if any", + TP_HASH_TYPE_STRING_VARIANT_MAP, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_HINTS, param_spec); + + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (TpTestsSimpleChannelRequestClass, dbus_props_class)); +} + +TpTestsSimpleChannelRequest * +tp_tests_simple_channel_request_new (const gchar *path, + TpTestsSimpleConnection *conn, + const gchar *account_path, + gint64 user_action_time, + const gchar *preferred_handler, + GPtrArray *requests, + GHashTable *hints) +{ + return tp_tests_object_new_static_class ( + TP_TESTS_TYPE_SIMPLE_CHANNEL_REQUEST, + "path", path, + "connection", conn, + "account", account_path, + "user-action-time", user_action_time, + "preferred-handler", preferred_handler, + "requests", requests, + "hints", hints, + NULL); +} diff --git a/tests/lib/telepathy/contactlist/simple-channel-request.h b/tests/lib/telepathy/contactlist/simple-channel-request.h new file mode 100644 index 00000000..60ea3be6 --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-channel-request.h @@ -0,0 +1,70 @@ +/* + * simple-channel-request.h - header for a simple channel request service. + * + * Copyright Ā© 2010 Collabora Ltd. + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_SIMPLE_CHANNEL_REQUEST_H__ +#define __TP_TESTS_SIMPLE_CHANNEL_REQUEST_H__ + +#include <glib-object.h> + +#include <telepathy-glib/telepathy-glib.h> + +#include "simple-conn.h" + +G_BEGIN_DECLS + +typedef struct _TpTestsSimpleChannelRequest TpTestsSimpleChannelRequest; +typedef struct _TpTestsSimpleChannelRequestClass TpTestsSimpleChannelRequestClass; +typedef struct _TpTestsSimpleChannelRequestPrivate TpTestsSimpleChannelRequestPrivate; + +struct _TpTestsSimpleChannelRequestClass { + GObjectClass parent_class; + TpDBusPropertiesMixinClass dbus_props_class; +}; + +struct _TpTestsSimpleChannelRequest { + GObject parent; + + TpTestsSimpleChannelRequestPrivate *priv; +}; + +GType tp_tests_simple_channel_request_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_SIMPLE_CHANNEL_REQUEST \ + (tp_tests_simple_channel_request_get_type ()) +#define SIMPLE_CHANNEL_REQUEST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_REQUEST, \ + TpTestsSimpleChannelRequest)) +#define SIMPLE_CHANNEL_REQUEST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_SIMPLE_CHANNEL_REQUEST, \ + TpTestsSimpleChannelRequestClass)) +#define SIMPLE_IS_CHANNEL_REQUEST(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_REQUEST)) +#define SIMPLE_IS_CHANNEL_REQUEST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_SIMPLE_CHANNEL_REQUEST)) +#define SIMPLE_CHANNEL_REQUEST_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_SIMPLE_CHANNEL_REQUEST, \ + TpTestsSimpleChannelRequestClass)) + +TpTestsSimpleChannelRequest * +tp_tests_simple_channel_request_new (const gchar *path, + TpTestsSimpleConnection *conn, + const gchar *account_path, + gint64 user_action_time, + const gchar *preferred_handler, + GPtrArray *requests, + GHashTable *hints); + +GHashTable * tp_tests_simple_channel_request_dup_immutable_props ( + TpTestsSimpleChannelRequest *self); + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_SIMPLE_CHANNEL_REQUEST_H__ */ diff --git a/tests/lib/telepathy/contactlist/simple-client.c b/tests/lib/telepathy/contactlist/simple-client.c new file mode 100644 index 00000000..c7431644 --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-client.c @@ -0,0 +1,250 @@ +/* + * simple-client.c - a simple client + * + * Copyright Ā© 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "simple-client.h" + +#include <string.h> + +#include <dbus/dbus-glib.h> + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +#include "tests/lib/util.h" + +G_DEFINE_TYPE (TpTestsSimpleClient, tp_tests_simple_client, TP_TYPE_BASE_CLIENT) + +static void +simple_observe_channels ( + TpBaseClient *client, + TpAccount *account, + TpConnection *connection, + GList *channels, + TpChannelDispatchOperation *dispatch_operation, + GList *requests, + TpObserveChannelsContext *context) +{ + TpTestsSimpleClient *self = TP_TESTS_SIMPLE_CLIENT (client); + GHashTable *info; + gboolean fail; + GList *l; + + /* Fail if caller set the fake "FAIL" info */ + g_object_get (context, "observer-info", &info, NULL); + fail = tp_asv_get_boolean (info, "FAIL", NULL); + g_hash_table_unref (info); + + if (self->observe_ctx != NULL) + { + g_object_unref (self->observe_ctx); + self->observe_ctx = NULL; + } + + if (fail) + { + GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "No observation for you!" }; + + tp_observe_channels_context_fail (context, &error); + return; + } + + g_assert (TP_IS_ACCOUNT (account)); + g_assert (tp_proxy_is_prepared (account, TP_ACCOUNT_FEATURE_CORE)); + + g_assert (TP_IS_CONNECTION (connection)); + g_assert (tp_proxy_is_prepared (connection, TP_CONNECTION_FEATURE_CORE)); + + g_assert_cmpuint (g_list_length (channels), >, 0); + for (l = channels; l != NULL; l = g_list_next (l)) + { + TpChannel *channel = l->data; + + g_assert (TP_IS_CHANNEL (channel)); + g_assert (tp_proxy_is_prepared (channel, TP_CHANNEL_FEATURE_CORE) || + tp_proxy_get_invalidated (channel) != NULL); + } + + if (dispatch_operation != NULL) + g_assert (TP_IS_CHANNEL_DISPATCH_OPERATION (dispatch_operation)); + + for (l = requests; l != NULL; l = g_list_next (l)) + { + TpChannelRequest *request = l->data; + + g_assert (TP_IS_CHANNEL_REQUEST (request)); + } + + self->observe_ctx = g_object_ref (context); + tp_observe_channels_context_accept (context); +} + +static void +simple_add_dispatch_operation ( + TpBaseClient *client, + TpAccount *account, + TpConnection *connection, + GList *channels, + TpChannelDispatchOperation *dispatch_operation, + TpAddDispatchOperationContext *context) +{ + TpTestsSimpleClient *self = TP_TESTS_SIMPLE_CLIENT (client); + GList *l; + + g_assert (TP_IS_ACCOUNT (account)); + g_assert (tp_proxy_is_prepared (account, TP_ACCOUNT_FEATURE_CORE)); + + g_assert (TP_IS_CONNECTION (connection)); + g_assert (tp_proxy_is_prepared (connection, TP_CONNECTION_FEATURE_CORE)); + + g_assert (TP_IS_CHANNEL_DISPATCH_OPERATION (dispatch_operation)); + g_assert (tp_proxy_is_prepared (dispatch_operation, + TP_CHANNEL_DISPATCH_OPERATION_FEATURE_CORE) || + tp_proxy_get_invalidated (dispatch_operation) != NULL); + + if (self->add_dispatch_ctx != NULL) + { + g_object_unref (self->add_dispatch_ctx); + self->add_dispatch_ctx = NULL; + } + + g_assert_cmpuint (g_list_length (channels), >, 0); + for (l = channels; l != NULL; l = g_list_next (l)) + { + TpChannel *channel = l->data; + + g_assert (TP_IS_CHANNEL (channel)); + g_assert (tp_proxy_is_prepared (channel, TP_CHANNEL_FEATURE_CORE) || + tp_proxy_get_invalidated (channel) != NULL); + } + + self->add_dispatch_ctx = g_object_ref (context); + tp_add_dispatch_operation_context_accept (context); +} + +static void +simple_handle_channels (TpBaseClient *client, + TpAccount *account, + TpConnection *connection, + GList *channels, + GList *requests_satisfied, + gint64 user_action_time, + TpHandleChannelsContext *context) +{ + TpTestsSimpleClient *self = TP_TESTS_SIMPLE_CLIENT (client); + GList *l; + + if (self->handle_channels_ctx != NULL) + { + g_object_unref (self->handle_channels_ctx); + self->handle_channels_ctx = NULL; + } + + g_assert (TP_IS_ACCOUNT (account)); + g_assert (tp_proxy_is_prepared (account, TP_ACCOUNT_FEATURE_CORE)); + + g_assert (TP_IS_CONNECTION (connection)); + g_assert (tp_proxy_is_prepared (connection, TP_CONNECTION_FEATURE_CORE)); + + g_assert_cmpuint (g_list_length (channels), >, 0); + for (l = channels; l != NULL; l = g_list_next (l)) + { + TpChannel *channel = l->data; + + g_assert (TP_IS_CHANNEL (channel)); + g_assert (tp_proxy_is_prepared (channel, TP_CHANNEL_FEATURE_CORE) || + tp_proxy_get_invalidated (channel) != NULL); + } + + for (l = requests_satisfied; l != NULL; l = g_list_next (l)) + { + TpChannelRequest *request = l->data; + + g_assert (TP_IS_CHANNEL_REQUEST (request)); + } + + self->handle_channels_ctx = g_object_ref (context); + tp_handle_channels_context_accept (context); +} + +static void +tp_tests_simple_client_init (TpTestsSimpleClient *self) +{ +} + +static void +tp_tests_simple_client_dispose (GObject *object) +{ + TpTestsSimpleClient *self = TP_TESTS_SIMPLE_CLIENT (object); + void (*dispose) (GObject *) = + G_OBJECT_CLASS (tp_tests_simple_client_parent_class)->dispose; + + if (self->observe_ctx != NULL) + { + g_object_unref (self->observe_ctx); + self->observe_ctx = NULL; + } + + if (self->add_dispatch_ctx != NULL) + { + g_object_unref (self->add_dispatch_ctx); + self->add_dispatch_ctx = NULL; + } + + if (self->handle_channels_ctx != NULL) + { + g_object_unref (self->handle_channels_ctx); + self->handle_channels_ctx = NULL; + } + + if (dispose != NULL) + dispose (object); +} + +static void +tp_tests_simple_client_class_init (TpTestsSimpleClientClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + TpBaseClientClass *base_class = TP_BASE_CLIENT_CLASS (klass); + + object_class->dispose = tp_tests_simple_client_dispose; + + tp_base_client_implement_observe_channels (base_class, + simple_observe_channels); + + tp_base_client_implement_add_dispatch_operation (base_class, + simple_add_dispatch_operation); + + tp_base_client_implement_handle_channels (base_class, + simple_handle_channels); +} + +TpTestsSimpleClient * +tp_tests_simple_client_new (TpClientFactory *factory, + const gchar *name, + gboolean uniquify_name) +{ + return tp_tests_object_new_static_class (TP_TESTS_TYPE_SIMPLE_CLIENT, + "factory", factory, + "name", name, + "uniquify-name", uniquify_name, + NULL); +} + +TpTestsSimpleClient * +tp_tests_simple_client_new_with_am (TpAccountManager *account_mgr, + const gchar *name, + gboolean uniquify_name) +{ + return tp_tests_simple_client_new (tp_proxy_get_factory (account_mgr), + name, uniquify_name); +} diff --git a/tests/lib/telepathy/contactlist/simple-client.h b/tests/lib/telepathy/contactlist/simple-client.h new file mode 100644 index 00000000..b6f7b5f8 --- /dev/null +++ b/tests/lib/telepathy/contactlist/simple-client.h @@ -0,0 +1,64 @@ +/* + * simple-client.h - header for a simple client + * + * Copyright Ā© 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_TESTS_SIMPLE_CLIENT_H__ +#define __TP_TESTS_SIMPLE_CLIENT_H__ + +#include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + +G_BEGIN_DECLS + +typedef struct _TpTestsSimpleClient TpTestsSimpleClient; +typedef struct _TpTestsSimpleClientClass TpTestsSimpleClientClass; + +struct _TpTestsSimpleClientClass { + TpBaseClientClass parent_class; +}; + +struct _TpTestsSimpleClient { + TpBaseClient parent; + + TpObserveChannelsContext *observe_ctx; + TpAddDispatchOperationContext *add_dispatch_ctx; + TpHandleChannelsContext *handle_channels_ctx; +}; + +GType tp_tests_simple_client_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_SIMPLE_CLIENT \ + (tp_tests_simple_client_get_type ()) +#define TP_TESTS_SIMPLE_CLIENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_SIMPLE_CLIENT, \ + TpTestsSimpleClient)) +#define TP_TESTS_SIMPLE_CLIENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_SIMPLE_CLIENT, \ + TpTestsSimpleClientClass)) +#define SIMPLE_IS_CLIENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_SIMPLE_CLIENT)) +#define SIMPLE_IS_CLIENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_SIMPLE_CLIENT)) +#define TP_TESTS_SIMPLE_CLIENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_SIMPLE_CLIENT, \ + TpTestsSimpleClientClass)) + +TpTestsSimpleClient * tp_tests_simple_client_new (TpClientFactory *factory, + const gchar *name, + gboolean uniquify_name); + +TpTestsSimpleClient * tp_tests_simple_client_new_with_am ( + TpAccountManager *account_mgr, + const gchar *name, + gboolean uniquify_name); + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_SIMPLE_CONN_H__ */ diff --git a/tests/lib/telepathy/contactlist/simple-conn.c b/tests/lib/telepathy/contactlist/simple-conn.c index e6ee214e..fa7bfdac 100644 --- a/tests/lib/telepathy/contactlist/simple-conn.c +++ b/tests/lib/telepathy/contactlist/simple-conn.c @@ -17,36 +17,32 @@ #include <dbus/dbus-glib.h> -#include <telepathy-glib/dbus.h> -#include <telepathy-glib/errors.h> -#include <telepathy-glib/gtypes.h> -#include <telepathy-glib/handle-repo-dynamic.h> -#include <telepathy-glib/interfaces.h> -#include <telepathy-glib/util.h> - -#include "textchan-null.h" +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +#include "echo-chan.h" #include "room-list-chan.h" #include "util.h" -static void conn_iface_init (TpSvcConnectionClass *); +static void props_iface_init (TpSvcDBusPropertiesClass *); G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleConnection, tp_tests_simple_connection, TP_TYPE_BASE_CONNECTION, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION, conn_iface_init)) + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, props_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION, NULL)) /* type definition stuff */ enum { PROP_ACCOUNT = 1, - PROP_BREAK_PROPS = 2, - PROP_DBUS_STATUS = 3, + PROP_DBUS_STATUS, N_PROPS }; enum { - SIGNAL_GOT_SELF_HANDLE, + SIGNAL_GOT_ALL, N_SIGNALS }; @@ -57,13 +53,10 @@ struct _TpTestsSimpleConnectionPrivate gchar *account; guint connect_source; guint disconnect_source; - gboolean break_fastpath_props; /* TpHandle => reffed TpTestsTextChannelNull */ GHashTable *text_channels; TpTestsRoomListChan *room_list_chan; - - GError *get_self_handle_error /* initially NULL */ ; }; static void @@ -88,16 +81,7 @@ get_property (GObject *object, case PROP_ACCOUNT: g_value_set_string (value, self->priv->account); break; - case PROP_BREAK_PROPS: - g_value_set_boolean (value, self->priv->break_fastpath_props); - break; case PROP_DBUS_STATUS: - if (self->priv->break_fastpath_props) - { - g_debug ("returning broken value for Connection.Status"); - g_value_set_uint (value, 0xdeadbeefU); - } - else { g_value_set_uint (value, tp_base_connection_get_status (TP_BASE_CONNECTION (self))); @@ -121,9 +105,6 @@ set_property (GObject *object, g_free (self->priv->account); self->priv->account = g_utf8_strdown (g_value_get_string (value), -1); break; - case PROP_BREAK_PROPS: - self->priv->break_fastpath_props = g_value_get_boolean (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); } @@ -155,7 +136,6 @@ finalize (GObject *object) g_source_remove (self->priv->disconnect_source); } - g_clear_error (&self->priv->get_self_handle_error); g_free (self->priv->account); G_OBJECT_CLASS (tp_tests_simple_connection_parent_class)->finalize (object); @@ -203,7 +183,7 @@ create_handle_repos (TpBaseConnection *conn, } static GPtrArray * -create_channel_factories (TpBaseConnection *conn) +create_channel_managers (TpBaseConnection *conn) { return g_ptr_array_sized_new (0); } @@ -284,6 +264,19 @@ shut_down (TpBaseConnection *conn) conn); } +static GPtrArray * +get_interfaces_always_present (TpBaseConnection *base) +{ + GPtrArray *interfaces; + + interfaces = TP_BASE_CONNECTION_CLASS ( + tp_tests_simple_connection_parent_class)->get_interfaces_always_present (base); + + g_ptr_array_add (interfaces, TP_IFACE_CONNECTION_INTERFACE_REQUESTS); + + return interfaces; +} + static void tp_tests_simple_connection_class_init (TpTestsSimpleConnectionClass *klass) { @@ -291,8 +284,6 @@ tp_tests_simple_connection_class_init (TpTestsSimpleConnectionClass *klass) (TpBaseConnectionClass *) klass; GObjectClass *object_class = (GObjectClass *) klass; GParamSpec *param_spec; - static const gchar *interfaces_always_present[] = { - TP_IFACE_CONNECTION_INTERFACE_REQUESTS, NULL }; object_class->get_property = get_property; object_class->set_property = set_property; @@ -302,23 +293,17 @@ tp_tests_simple_connection_class_init (TpTestsSimpleConnectionClass *klass) base_class->create_handle_repos = create_handle_repos; base_class->get_unique_connection_name = get_unique_connection_name; - base_class->create_channel_factories = create_channel_factories; + base_class->create_channel_managers = create_channel_managers; base_class->start_connecting = start_connecting; base_class->shut_down = shut_down; - base_class->interfaces_always_present = interfaces_always_present; + base_class->get_interfaces_always_present = get_interfaces_always_present; param_spec = g_param_spec_string ("account", "Account name", "The username of this user", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec); - param_spec = g_param_spec_boolean ("break-0192-properties", - "Break 0.19.2 properties", - "Break Connection D-Bus properties introduced in spec 0.19.2", FALSE, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_BREAK_PROPS, param_spec); - param_spec = g_param_spec_uint ("dbus-status", "Connection.Status", "The connection status as visible on D-Bus (overridden so can break it)", @@ -327,7 +312,7 @@ tp_tests_simple_connection_class_init (TpTestsSimpleConnectionClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DBUS_STATUS, param_spec); - signals[SIGNAL_GOT_SELF_HANDLE] = g_signal_new ("got-self-handle", + signals[SIGNAL_GOT_ALL] = g_signal_new ("got-all", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, @@ -366,11 +351,10 @@ tp_tests_simple_connection_ensure_text_chan (TpTestsSimpleConnection *self, const gchar *target_id, GHashTable **props) { - TpTestsTextChannelNull *chan; + TpTestsEchoChannel *chan; gchar *chan_path; TpHandleRepoIface *contact_repo; TpHandle handle; - static guint count = 0; TpBaseConnection *base_conn = (TpBaseConnection *) self; /* Get contact handle */ @@ -382,21 +366,12 @@ tp_tests_simple_connection_ensure_text_chan (TpTestsSimpleConnection *self, chan = g_hash_table_lookup (self->priv->text_channels, GUINT_TO_POINTER (handle)); - if (chan != NULL) + if (chan == NULL) { - /* Channel already exist, reuse it */ - g_object_get (chan, "object-path", &chan_path, NULL); - } - else - { - chan_path = g_strdup_printf ("%s/Channel%u", - tp_base_connection_get_object_path (base_conn), count++); - - chan = TP_TESTS_TEXT_CHANNEL_NULL ( + chan = TP_TESTS_ECHO_CHANNEL ( tp_tests_object_new_static_class ( - TP_TESTS_TYPE_TEXT_CHANNEL_NULL, + TP_TESTS_TYPE_ECHO_CHANNEL, "connection", self, - "object-path", chan_path, "handle", handle, NULL)); @@ -404,8 +379,10 @@ tp_tests_simple_connection_ensure_text_chan (TpTestsSimpleConnection *self, chan); } + g_object_get (chan, "object-path", &chan_path, NULL); + if (props != NULL) - *props = tp_tests_text_channel_get_props (chan); + g_object_get (chan, "channel-properties", props, NULL); return chan_path; } @@ -455,44 +432,25 @@ tp_tests_simple_connection_ensure_room_list_chan (TpTestsSimpleConnection *self, return chan_path; } -void -tp_tests_simple_connection_set_get_self_handle_error ( - TpTestsSimpleConnection *self, - GQuark domain, - gint code, - const gchar *message) -{ - self->priv->get_self_handle_error = g_error_new_literal (domain, code, - message); -} - static void -get_self_handle (TpSvcConnection *iface, +get_all (TpSvcDBusProperties *iface, + const gchar *interface_name, DBusGMethodInvocation *context) { - TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (iface); - TpBaseConnection *base = TP_BASE_CONNECTION (iface); - - g_assert (TP_IS_BASE_CONNECTION (base)); - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - if (self->priv->get_self_handle_error != NULL) - { - dbus_g_method_return_error (context, self->priv->get_self_handle_error); - return; - } + GHashTable *values = tp_dbus_properties_mixin_dup_all (G_OBJECT (iface), + interface_name); - tp_svc_connection_return_from_get_self_handle (context, - tp_base_connection_get_self_handle (base)); - g_signal_emit (self, signals[SIGNAL_GOT_SELF_HANDLE], 0); + tp_svc_dbus_properties_return_from_get_all (context, values); + g_hash_table_unref (values); + g_signal_emit (iface, signals[SIGNAL_GOT_ALL], + g_quark_from_string (interface_name)); } static void -conn_iface_init (TpSvcConnectionClass *iface) +props_iface_init (TpSvcDBusPropertiesClass *iface) { -#define IMPLEMENT(prefix,x) \ - tp_svc_connection_implement_##x (iface, prefix##x) - IMPLEMENT(,get_self_handle); +#define IMPLEMENT(x) \ + tp_svc_dbus_properties_implement_##x (iface, x) + IMPLEMENT (get_all); #undef IMPLEMENT } diff --git a/tests/lib/telepathy/contactlist/simple-conn.h b/tests/lib/telepathy/contactlist/simple-conn.h index 837400bc..ffe5778d 100644 --- a/tests/lib/telepathy/contactlist/simple-conn.h +++ b/tests/lib/telepathy/contactlist/simple-conn.h @@ -13,7 +13,7 @@ #define __TP_TESTS_SIMPLE_CONN_H__ #include <glib-object.h> -#include <telepathy-glib/base-connection.h> +#include <telepathy-glib/telepathy-glib.h> G_BEGIN_DECLS @@ -66,12 +66,6 @@ gchar * tp_tests_simple_connection_ensure_text_chan ( const gchar *target_id, GHashTable **props); -void tp_tests_simple_connection_set_get_self_handle_error ( - TpTestsSimpleConnection *self, - GQuark domain, - gint code, - const gchar *message); - gchar * tp_tests_simple_connection_ensure_room_list_chan ( TpTestsSimpleConnection *self, const gchar *server, diff --git a/tests/lib/telepathy/contactlist/stream-tube-chan.c b/tests/lib/telepathy/contactlist/stream-tube-chan.c new file mode 100644 index 00000000..e1184af8 --- /dev/null +++ b/tests/lib/telepathy/contactlist/stream-tube-chan.c @@ -0,0 +1,650 @@ +/* + * stream-tube-chan.c - Simple stream tube channel + * + * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "config.h" + +#include "stream-tube-chan.h" +#include "util.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +#ifdef HAVE_GIO_UNIX +#include <gio/gunixsocketaddress.h> +#include <gio/gunixconnection.h> +#endif + +#include <glib/gstdio.h> + +enum +{ + PROP_SERVICE = 1, + PROP_SUPPORTED_SOCKET_TYPES, + PROP_PARAMETERS, + PROP_STATE, +}; + +enum +{ + SIG_INCOMING_CONNECTION, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0, }; + + +struct _TpTestsStreamTubeChannelPrivate { + TpTubeChannelState state; + GHashTable *supported_socket_types; + + /* Accepting side */ + GSocketService *service; + GValue *access_control_param; + + /* Offering side */ + TpSocketAddressType address_type; + GValue *address; + gchar *unix_address; + gchar *unix_tmpdir; + guint connection_id; + + TpSocketAccessControl access_control; +}; + +static void +create_supported_socket_types (TpTestsStreamTubeChannel *self) +{ + TpSocketAccessControl access_control; + GArray *unix_tab; + + g_assert (self->priv->supported_socket_types == NULL); + self->priv->supported_socket_types = g_hash_table_new_full (NULL, NULL, + NULL, _tp_destroy_socket_control_list); + + /* Socket_Address_Type_Unix */ + unix_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl), + 1); + access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; + g_array_append_val (unix_tab, access_control); + + g_hash_table_insert (self->priv->supported_socket_types, + GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_UNIX), unix_tab); +} + +static void +tp_tests_stream_tube_channel_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + TpTestsStreamTubeChannel *self = (TpTestsStreamTubeChannel *) object; + + switch (property_id) + { + case PROP_SERVICE: + g_value_set_string (value, "test-service"); + break; + + case PROP_SUPPORTED_SOCKET_TYPES: + g_value_set_boxed (value, + self->priv->supported_socket_types); + break; + + case PROP_PARAMETERS: + g_value_take_boxed (value, tp_asv_new ( + "badger", G_TYPE_UINT, 42, + NULL)); + break; + + case PROP_STATE: + g_value_set_uint (value, self->priv->state); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +tp_tests_stream_tube_channel_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + TpTestsStreamTubeChannel *self = (TpTestsStreamTubeChannel *) object; + + switch (property_id) + { + case PROP_SUPPORTED_SOCKET_TYPES: + self->priv->supported_socket_types = g_value_dup_boxed (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void stream_tube_iface_init (gpointer iface, gpointer data); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (TpTestsStreamTubeChannel, + tp_tests_stream_tube_channel, + TP_TYPE_BASE_CHANNEL, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_STREAM_TUBE, + stream_tube_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_TUBE, + NULL); + ) + +/* type definition stuff */ + +static GPtrArray * +tp_tests_stream_tube_channel_get_interfaces (TpBaseChannel *self) +{ + GPtrArray *interfaces; + + interfaces = TP_BASE_CHANNEL_CLASS ( + tp_tests_stream_tube_channel_parent_class)->get_interfaces (self); + + g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_TUBE); + return interfaces; +}; + +static void +tp_tests_stream_tube_channel_init (TpTestsStreamTubeChannel *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), + TP_TESTS_TYPE_STREAM_TUBE_CHANNEL, TpTestsStreamTubeChannelPrivate); +} + +static GObject * +constructor (GType type, + guint n_props, + GObjectConstructParam *props) +{ + GObject *object = + G_OBJECT_CLASS (tp_tests_stream_tube_channel_parent_class)->constructor ( + type, n_props, props); + TpTestsStreamTubeChannel *self = TP_TESTS_STREAM_TUBE_CHANNEL (object); + + if (tp_base_channel_is_requested (TP_BASE_CHANNEL (self))) + self->priv->state = TP_TUBE_CHANNEL_STATE_NOT_OFFERED; + else + self->priv->state = TP_TUBE_CHANNEL_STATE_LOCAL_PENDING; + + if (self->priv->supported_socket_types == NULL) + create_supported_socket_types (self); + + tp_base_channel_register (TP_BASE_CHANNEL (self)); + + return object; +} + +static void +dispose (GObject *object) +{ + TpTestsStreamTubeChannel *self = (TpTestsStreamTubeChannel *) object; + + if (self->priv->service != NULL) + { + g_socket_service_stop (self->priv->service); + tp_clear_object (&self->priv->service); + } + + tp_clear_pointer (&self->priv->address, tp_g_value_slice_free); + tp_clear_pointer (&self->priv->supported_socket_types, g_hash_table_unref); + tp_clear_pointer (&self->priv->access_control_param, tp_g_value_slice_free); + + if (self->priv->unix_address != NULL) + g_unlink (self->priv->unix_address); + + tp_clear_pointer (&self->priv->unix_address, g_free); + + if (self->priv->unix_tmpdir != NULL) + g_rmdir (self->priv->unix_tmpdir); + + tp_clear_pointer (&self->priv->unix_tmpdir, g_free); + + ((GObjectClass *) tp_tests_stream_tube_channel_parent_class)->dispose ( + object); +} + +static void +channel_close (TpBaseChannel *channel) +{ + tp_base_channel_destroyed (channel); +} + +static void +fill_immutable_properties (TpBaseChannel *chan, + GHashTable *properties) +{ + TpBaseChannelClass *klass = TP_BASE_CHANNEL_CLASS ( + tp_tests_stream_tube_channel_parent_class); + + klass->fill_immutable_properties (chan, properties); + + tp_dbus_properties_mixin_fill_properties_hash ( + G_OBJECT (chan), properties, + TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, "Service", + TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, "SupportedSocketTypes", + NULL); + + if (!tp_base_channel_is_requested (chan)) + { + /* Parameters is immutable only for incoming tubes */ + tp_dbus_properties_mixin_fill_properties_hash ( + G_OBJECT (chan), properties, + TP_IFACE_CHANNEL_INTERFACE_TUBE, "Parameters", + NULL); + } +} + +static void +tp_tests_stream_tube_channel_class_init (TpTestsStreamTubeChannelClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + GParamSpec *param_spec; + static TpDBusPropertiesMixinPropImpl stream_tube_props[] = { + { "Service", "service", NULL, }, + { "SupportedSocketTypes", "supported-socket-types", NULL }, + { NULL } + }; + static TpDBusPropertiesMixinPropImpl tube_props[] = { + { "Parameters", "parameters", NULL, }, + { "State", "state", NULL, }, + { NULL } + }; + + object_class->constructor = constructor; + object_class->get_property = tp_tests_stream_tube_channel_get_property; + object_class->set_property = tp_tests_stream_tube_channel_set_property; + object_class->dispose = dispose; + + base_class->channel_type = TP_IFACE_CHANNEL_TYPE_STREAM_TUBE; + base_class->get_interfaces = tp_tests_stream_tube_channel_get_interfaces; + base_class->close = channel_close; + base_class->fill_immutable_properties = fill_immutable_properties; + + /* base_class->target_handle_type is defined in subclasses */ + + param_spec = g_param_spec_string ("service", "service name", + "the service associated with this tube object.", + "", + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_SERVICE, param_spec); + + param_spec = g_param_spec_boxed ( + "supported-socket-types", "Supported socket types", + "GHashTable containing supported socket types.", + TP_HASH_TYPE_SUPPORTED_SOCKET_MAP, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_SUPPORTED_SOCKET_TYPES, + param_spec); + + param_spec = g_param_spec_boxed ( + "parameters", "Parameters", + "parameters of the tube", + TP_HASH_TYPE_STRING_VARIANT_MAP, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_PARAMETERS, + param_spec); + + param_spec = g_param_spec_uint ( + "state", "TpTubeState", + "state of the tube", + 0, TP_NUM_TUBE_CHANNEL_STATES - 1, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_STATE, + param_spec); + + signals[SIG_INCOMING_CONNECTION] = g_signal_new ("incoming-connection", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, + 1, G_TYPE_IO_STREAM); + + tp_dbus_properties_mixin_implement_interface (object_class, + TP_IFACE_QUARK_CHANNEL_TYPE_STREAM_TUBE, + tp_dbus_properties_mixin_getter_gobject_properties, NULL, + stream_tube_props); + + tp_dbus_properties_mixin_implement_interface (object_class, + TP_IFACE_QUARK_CHANNEL_INTERFACE_TUBE, + tp_dbus_properties_mixin_getter_gobject_properties, NULL, + tube_props); + + g_type_class_add_private (object_class, + sizeof (TpTestsStreamTubeChannelPrivate)); +} + +static void +change_state (TpTestsStreamTubeChannel *self, + TpTubeChannelState state) +{ + self->priv->state = state; + + tp_svc_channel_interface_tube_emit_tube_channel_state_changed (self, state); +} + +/* Return the address of the socket which has been shared over the tube */ +GSocketAddress * +tp_tests_stream_tube_channel_get_server_address (TpTestsStreamTubeChannel *self) +{ + return tp_g_socket_address_from_variant (self->priv->address_type, + self->priv->address, NULL); +} + +static gboolean +check_address_type (TpTestsStreamTubeChannel *self, + TpSocketAddressType address_type, + TpSocketAccessControl access_control) +{ + GArray *arr; + guint i; + + arr = g_hash_table_lookup (self->priv->supported_socket_types, + GUINT_TO_POINTER (address_type)); + if (arr == NULL) + return FALSE; + + for (i = 0; i < arr->len; i++) + { + if (g_array_index (arr, TpSocketAccessControl, i) == access_control) + return TRUE; + } + + return FALSE; +} + +static void +stream_tube_offer (TpSvcChannelTypeStreamTube *iface, + guint address_type, + const GValue *address, + guint access_control, + GHashTable *parameters, + DBusGMethodInvocation *context) +{ + TpTestsStreamTubeChannel *self = (TpTestsStreamTubeChannel *) iface; + GError *error = NULL; + + if (self->priv->state != TP_TUBE_CHANNEL_STATE_NOT_OFFERED) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Tube is not in the not offered state"); + goto fail; + } + + if (!check_address_type (self, address_type, access_control)) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Address type not supported with this access control"); + goto fail; + } + + self->priv->address_type = address_type; + self->priv->address = tp_g_value_slice_dup (address); + self->priv->access_control = access_control; + + change_state (self, TP_TUBE_CHANNEL_STATE_REMOTE_PENDING); + + tp_svc_channel_type_stream_tube_return_from_offer (context); + return; + +fail: + dbus_g_method_return_error (context, error); + g_error_free (error); +} + +static void +service_incoming_cb (GSocketService *service, + GSocketConnection *connection, + GObject *source_object, + gpointer user_data) +{ + TpTestsStreamTubeChannel *self = user_data; + GError *error = NULL; + + if (self->priv->access_control == TP_SOCKET_ACCESS_CONTROL_CREDENTIALS) + { +#ifdef HAVE_GIO_UNIX + GCredentials *creds; + guchar byte; + + /* FIXME: we should an async version of this API (bgo #629503) */ + creds = tp_unix_connection_receive_credentials_with_byte ( + connection, &byte, NULL, &error); + g_assert_no_error (error); + + g_assert_cmpuint (byte, ==, + g_value_get_uchar (self->priv->access_control_param)); + g_object_unref (creds); +#else + /* Tests shouldn't use this if not supported */ + g_assert_not_reached (); +#endif + } + else if (self->priv->access_control == TP_SOCKET_ACCESS_CONTROL_PORT) + { + GSocketAddress *addr; + guint16 port; + + addr = g_socket_connection_get_remote_address (connection, &error); + g_assert_no_error (error); + + port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); + + g_assert_cmpuint (port, ==, + g_value_get_uint (self->priv->access_control_param)); + + g_object_unref (addr); + } + + tp_svc_channel_type_stream_tube_emit_new_local_connection (self, + self->priv->connection_id); + + self->priv->connection_id++; + + g_signal_emit (self, signals[SIG_INCOMING_CONNECTION], 0, connection); +} + +static void +stream_tube_accept (TpSvcChannelTypeStreamTube *iface, + TpSocketAddressType address_type, + TpSocketAccessControl access_control, + const GValue *access_control_param, + DBusGMethodInvocation *context) +{ + TpTestsStreamTubeChannel *self = (TpTestsStreamTubeChannel *) iface; + GError *error = NULL; + GValue *address; + + if (self->priv->state != TP_TUBE_CHANNEL_STATE_LOCAL_PENDING) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Tube is not in the local pending state"); + goto fail; + } + + if (!check_address_type (self, address_type, access_control)) + { + g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Address type not supported with this access control"); + goto fail; + } + + address = _tp_create_local_socket (address_type, access_control, + &self->priv->service, &self->priv->unix_address, + &self->priv->unix_tmpdir, &error); + tp_g_signal_connect_object (self->priv->service, "incoming", + G_CALLBACK (service_incoming_cb), self, 0); + + self->priv->access_control = access_control; + self->priv->access_control_param = tp_g_value_slice_dup ( + access_control_param); + + change_state (self, TP_TUBE_CHANNEL_STATE_OPEN); + + tp_svc_channel_type_stream_tube_return_from_accept (context, address); + + tp_g_value_slice_free (address); + return; + +fail: + dbus_g_method_return_error (context, error); + g_error_free (error); +} + +static void +stream_tube_iface_init (gpointer iface, + gpointer data) +{ + TpSvcChannelTypeStreamTubeClass *klass = iface; + +#define IMPLEMENT(x) tp_svc_channel_type_stream_tube_implement_##x (klass, stream_tube_##x) + IMPLEMENT(offer); + IMPLEMENT(accept); +#undef IMPLEMENT +} + +/* Called to emulate a peer connecting to an offered tube */ +void +tp_tests_stream_tube_channel_peer_connected (TpTestsStreamTubeChannel *self, + GIOStream *stream, + TpHandle handle) +{ + GValue *connection_param; + TpBaseChannel *base = (TpBaseChannel *) self; + TpBaseConnection *conn = tp_base_channel_get_connection (base); + TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, + TP_HANDLE_TYPE_CONTACT); + + if (self->priv->state == TP_TUBE_CHANNEL_STATE_REMOTE_PENDING) + change_state (self, TP_TUBE_CHANNEL_STATE_OPEN); + + g_assert (self->priv->state == TP_TUBE_CHANNEL_STATE_OPEN); + + switch (self->priv->access_control) + { + case TP_SOCKET_ACCESS_CONTROL_LOCALHOST: + connection_param = tp_g_value_slice_new_static_string ("dummy"); + break; + + case TP_SOCKET_ACCESS_CONTROL_CREDENTIALS: + { +#ifdef HAVE_GIO_UNIX + GError *error = NULL; + guchar byte = g_random_int_range (0, G_MAXUINT8); + + /* FIXME: we should an async version of this API (bgo #629503) */ + tp_unix_connection_send_credentials_with_byte ( + G_SOCKET_CONNECTION (stream), byte, NULL, &error); + g_assert_no_error (error); + + connection_param = tp_g_value_slice_new_byte (byte); +#else + /* Tests shouldn't use this if not supported */ + g_assert_not_reached (); +#endif + } + break; + + case TP_SOCKET_ACCESS_CONTROL_PORT: + { + GSocketAddress *addr; + GError *error = NULL; + + addr = g_socket_connection_get_local_address ( + G_SOCKET_CONNECTION (stream), &error); + g_assert_no_error (error); + + connection_param = tp_g_value_slice_new_take_boxed ( + TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4, + dbus_g_type_specialized_construct ( + TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4)); + + dbus_g_type_struct_set (connection_param, + 0, "badger", + 1, g_inet_socket_address_get_port ( + G_INET_SOCKET_ADDRESS (addr)), + G_MAXUINT); + + g_object_unref (addr); + } + break; + + default: + g_assert_not_reached (); + } + + tp_svc_channel_type_stream_tube_emit_new_remote_connection (self, handle, + tp_handle_inspect (contact_repo, handle), connection_param, + self->priv->connection_id); + + self->priv->connection_id++; + + tp_g_value_slice_free (connection_param); +} + +void +tp_tests_stream_tube_channel_last_connection_disconnected ( + TpTestsStreamTubeChannel *self, + const gchar *error) +{ + tp_svc_channel_type_stream_tube_emit_connection_closed (self, + self->priv->connection_id - 1, error, "kaboum"); +} + +/* Contact Stream Tube */ + +G_DEFINE_TYPE (TpTestsContactStreamTubeChannel, + tp_tests_contact_stream_tube_channel, + TP_TESTS_TYPE_STREAM_TUBE_CHANNEL) + +static void +tp_tests_contact_stream_tube_channel_init ( + TpTestsContactStreamTubeChannel *self) +{ +} + +static void +tp_tests_contact_stream_tube_channel_class_init ( + TpTestsContactStreamTubeChannelClass *klass) +{ + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + + base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; +} + +/* Room Stream Tube */ + +G_DEFINE_TYPE (TpTestsRoomStreamTubeChannel, + tp_tests_room_stream_tube_channel, + TP_TESTS_TYPE_STREAM_TUBE_CHANNEL) + +static void +tp_tests_room_stream_tube_channel_init ( + TpTestsRoomStreamTubeChannel *self) +{ +} + +static void +tp_tests_room_stream_tube_channel_class_init ( + TpTestsRoomStreamTubeChannelClass *klass) +{ + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + + base_class->target_handle_type = TP_HANDLE_TYPE_ROOM; +} diff --git a/tests/lib/telepathy/contactlist/stream-tube-chan.h b/tests/lib/telepathy/contactlist/stream-tube-chan.h new file mode 100644 index 00000000..26729127 --- /dev/null +++ b/tests/lib/telepathy/contactlist/stream-tube-chan.h @@ -0,0 +1,129 @@ +/* + * stream-tube-chan.h - Simple stream tube channel + * + * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TP_STREAM_TUBE_CHAN_H__ +#define __TP_STREAM_TUBE_CHAN_H__ + +#include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + +G_BEGIN_DECLS + +/* Base Class */ +typedef struct _TpTestsStreamTubeChannel TpTestsStreamTubeChannel; +typedef struct _TpTestsStreamTubeChannelClass TpTestsStreamTubeChannelClass; +typedef struct _TpTestsStreamTubeChannelPrivate TpTestsStreamTubeChannelPrivate; + +GType tp_tests_stream_tube_channel_get_type (void); + +#define TP_TESTS_TYPE_STREAM_TUBE_CHANNEL \ + (tp_tests_stream_tube_channel_get_type ()) +#define TP_TESTS_STREAM_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_STREAM_TUBE_CHANNEL, \ + TpTestsStreamTubeChannel)) +#define TP_TESTS_STREAM_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_STREAM_TUBE_CHANNEL, \ + TpTestsStreamTubeChannelClass)) +#define TP_TESTS_IS_STREAM_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_STREAM_TUBE_CHANNEL)) +#define TP_TESTS_IS_STREAM_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_STREAM_TUBE_CHANNEL)) +#define TP_TESTS_STREAM_TUBE_CHANNEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_STREAM_TUBE_CHANNEL, \ + TpTestsStreamTubeChannelClass)) + +struct _TpTestsStreamTubeChannelClass { + TpBaseChannelClass parent_class; + TpDBusPropertiesMixinClass dbus_properties_class; +}; + +struct _TpTestsStreamTubeChannel { + TpBaseChannel parent; + + TpTestsStreamTubeChannelPrivate *priv; +}; + +GSocketAddress * tp_tests_stream_tube_channel_get_server_address ( + TpTestsStreamTubeChannel *self); + +void tp_tests_stream_tube_channel_peer_connected ( + TpTestsStreamTubeChannel *self, + GIOStream *stream, + TpHandle handle); + +void tp_tests_stream_tube_channel_last_connection_disconnected ( + TpTestsStreamTubeChannel *self, + const gchar *error); + +/* Contact Stream Tube */ + +typedef struct _TpTestsContactStreamTubeChannel TpTestsContactStreamTubeChannel; +typedef struct _TpTestsContactStreamTubeChannelClass TpTestsContactStreamTubeChannelClass; + +GType tp_tests_contact_stream_tube_channel_get_type (void); + +#define TP_TESTS_TYPE_CONTACT_STREAM_TUBE_CHANNEL \ + (tp_tests_contact_stream_tube_channel_get_type ()) +#define TP_TESTS_CONTACT_STREAM_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_CONTACT_STREAM_TUBE_CHANNEL, \ + TpTestsContactStreamTubeChannel)) +#define TP_TESTS_CONTACT_STREAM_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_CONTACT_STREAM_TUBE_CHANNEL, \ + TpTestsContactStreamTubeChannelClass)) +#define TP_TESTS_IS_CONTACT_STREAM_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_CONTACT_STREAM_TUBE_CHANNEL)) +#define TP_TESTS_IS_CONTACT_STREAM_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_CONTACT_STREAM_TUBE_CHANNEL)) +#define TP_TESTS_CONTACT_STREAM_TUBE_CHANNEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_CONTACT_STREAM_TUBE_CHANNEL, \ + TpTestsContactStreamTubeChannelClass)) + +struct _TpTestsContactStreamTubeChannelClass { + TpTestsStreamTubeChannelClass parent_class; +}; + +struct _TpTestsContactStreamTubeChannel { + TpTestsStreamTubeChannel parent; +}; + +/* Room Stream Tube */ + +typedef struct _TpTestsRoomStreamTubeChannel TpTestsRoomStreamTubeChannel; +typedef struct _TpTestsRoomStreamTubeChannelClass TpTestsRoomStreamTubeChannelClass; + +GType tp_tests_room_stream_tube_channel_get_type (void); + +#define TP_TESTS_TYPE_ROOM_STREAM_TUBE_CHANNEL \ + (tp_tests_room_stream_tube_channel_get_type ()) +#define TP_TESTS_ROOM_STREAM_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_ROOM_STREAM_TUBE_CHANNEL, \ + TpTestsRoomStreamTubeChannel)) +#define TP_TESTS_ROOM_STREAM_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_ROOM_STREAM_TUBE_CHANNEL, \ + TpTestsRoomStreamTubeChannelClass)) +#define TP_TESTS_IS_ROOM_STREAM_TUBE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_ROOM_STREAM_TUBE_CHANNEL)) +#define TP_TESTS_IS_ROOM_STREAM_TUBE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_ROOM_STREAM_TUBE_CHANNEL)) +#define TP_TESTS_ROOM_STREAM_TUBE_CHANNEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_ROOM_STREAM_TUBE_CHANNEL, \ + TpTestsRoomStreamTubeChannelClass)) + +struct _TpTestsRoomStreamTubeChannelClass { + TpTestsStreamTubeChannelClass parent_class; +}; + +struct _TpTestsRoomStreamTubeChannel { + TpTestsStreamTubeChannel parent; +}; + +G_END_DECLS + +#endif /* #ifndef __TP_STREAM_TUBE_CHAN_H__ */ diff --git a/tests/lib/telepathy/contactlist/stub-object.c b/tests/lib/telepathy/contactlist/stub-object.c new file mode 100644 index 00000000..14828768 --- /dev/null +++ b/tests/lib/telepathy/contactlist/stub-object.c @@ -0,0 +1,68 @@ +#include "config.h" + +#include "stub-object.h" + +G_DEFINE_TYPE (TpTestsStubObject, tp_tests_stub_object, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_NAME, + N_PROPS +}; + +static void +stub_object_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *param_spec) +{ + switch (prop_id) + { + case PROP_NAME: + g_value_set_string (value, "Bruce"); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, param_spec); + break; + } +} + +static void +stub_object_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *param_spec) +{ + switch (prop_id) + { + case PROP_NAME: + /* do nothing */ + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, param_spec); + break; + } +} + +static void +tp_tests_stub_object_class_init (TpTestsStubObjectClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + + object_class->get_property = stub_object_get_property; + object_class->set_property = stub_object_set_property; + + g_object_class_install_property (object_class, PROP_NAME, + g_param_spec_string ("name", + "Name", + "The name of the stub object", + "Bruce", + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); +} + +static void +tp_tests_stub_object_init (TpTestsStubObject *self) +{ +} diff --git a/tests/lib/telepathy/contactlist/stub-object.h b/tests/lib/telepathy/contactlist/stub-object.h new file mode 100644 index 00000000..ccdb0940 --- /dev/null +++ b/tests/lib/telepathy/contactlist/stub-object.h @@ -0,0 +1,11 @@ +#ifndef __TP_TESTS_STUB_OBJECT_H__ +#define __TP_TESTS_STUB_OBJECT_H__ + +#include <glib-object.h> + +typedef struct { GObject p; } TpTestsStubObject; +typedef struct { GObjectClass p; } TpTestsStubObjectClass; + +GType tp_tests_stub_object_get_type (void); + +#endif /* #ifndef __TP_TESTS_STUB_OBJECT_H__ */ diff --git a/tests/lib/telepathy/contactlist/textchan-group.c b/tests/lib/telepathy/contactlist/textchan-group.c new file mode 100644 index 00000000..3b9b1797 --- /dev/null +++ b/tests/lib/telepathy/contactlist/textchan-group.c @@ -0,0 +1,329 @@ +/* + * a stub anonymous MUC + * + * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2008 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#include "config.h" + +#include "textchan-group.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +static void password_iface_init (gpointer iface, gpointer data); + +G_DEFINE_TYPE_WITH_CODE (TpTestsTextChannelGroup, + tp_tests_text_channel_group, TP_TYPE_BASE_CHANNEL, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, + tp_message_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP, + tp_group_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_PASSWORD, + password_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init)) + +static GPtrArray * +text_channel_group_get_interfaces (TpBaseChannel *self) +{ + GPtrArray *interfaces; + + interfaces = TP_BASE_CHANNEL_CLASS ( + tp_tests_text_channel_group_parent_class)->get_interfaces (self); + + g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_GROUP); + g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_PASSWORD); + return interfaces; +}; + +/* type definition stuff */ + +struct _TpTestsTextChannelGroupPrivate +{ + gboolean closed; + gboolean disposed; + + gchar *password; +}; + + +static gboolean +add_member (GObject *obj, + TpHandle handle, + const gchar *message, + GError **error) +{ + TpTestsTextChannelGroup *self = TP_TESTS_TEXT_CHANNEL_GROUP (obj); + TpIntset *add = tp_intset_new (); + GHashTable *details = tp_asv_new ( + "actor", G_TYPE_UINT, tp_base_connection_get_self_handle (self->conn), + "change-reason", G_TYPE_UINT, TP_CHANNEL_GROUP_CHANGE_REASON_NONE, + "message", G_TYPE_STRING, message, + NULL); + + tp_intset_add (add, handle); + tp_group_mixin_change_members (obj, add, NULL, NULL, NULL, details); + tp_intset_destroy (add); + + g_hash_table_unref (details); + + return TRUE; +} + +static gboolean +remove_with_reason (GObject *obj, + TpHandle handle, + const gchar *message, + guint reason, + GError **error) +{ + TpTestsTextChannelGroup *self = TP_TESTS_TEXT_CHANNEL_GROUP (obj); + TpGroupMixin *group = TP_GROUP_MIXIN (self); + + tp_clear_pointer (&self->removed_message, g_free); + + self->removed_handle = handle; + self->removed_message = g_strdup (message); + self->removed_reason = reason; + + if (handle == group->self_handle) + { + /* User wants to leave */ + if (!self->priv->closed) + { + self->priv->closed = TRUE; + tp_svc_channel_emit_closed (self); + } + + return TRUE; + } + + return TRUE; +} + +static void +tp_tests_text_channel_group_init (TpTestsTextChannelGroup *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + TP_TESTS_TYPE_TEXT_CHANNEL_GROUP, TpTestsTextChannelGroupPrivate); +} + +static void +text_send (GObject *object, + TpMessage *message, + TpMessageSendingFlags flags) +{ + /* silently swallow the message */ + tp_message_mixin_sent (object, message, 0, "", NULL); +} + +static void +constructed (GObject *object) +{ + TpTestsTextChannelGroup *self = TP_TESTS_TEXT_CHANNEL_GROUP (object); + TpHandleRepoIface *contact_repo; + TpChannelGroupFlags flags = 0; + TpBaseChannel *base = TP_BASE_CHANNEL (self); + const TpChannelTextMessageType types[] = { + TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, + TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION, + TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, + }; + const gchar * supported_content_types[] = { + "text/plain", + NULL + }; + + G_OBJECT_CLASS (tp_tests_text_channel_group_parent_class)->constructed ( + object); + + self->conn = tp_base_channel_get_connection (base); + + contact_repo = tp_base_connection_get_handles (self->conn, + TP_HANDLE_TYPE_CONTACT); + + tp_base_channel_register (base); + + tp_message_mixin_init (object, + G_STRUCT_OFFSET (TpTestsTextChannelGroup, message), + self->conn); + + tp_message_mixin_implement_sending (object, + text_send, G_N_ELEMENTS (types), types, 0, 0, + supported_content_types); + + flags |= TP_CHANNEL_GROUP_FLAG_CAN_ADD; + + tp_group_mixin_init (object, G_STRUCT_OFFSET (TpTestsTextChannelGroup, group), + contact_repo, + tp_base_connection_get_self_handle (self->conn)); + + tp_group_mixin_change_flags (object, flags, 0); +} + +static void +dispose (GObject *object) +{ + TpTestsTextChannelGroup *self = TP_TESTS_TEXT_CHANNEL_GROUP (object); + + if (self->priv->disposed) + return; + + self->priv->disposed = TRUE; + + if (!self->priv->closed) + { + tp_svc_channel_emit_closed (self); + } + + ((GObjectClass *) tp_tests_text_channel_group_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + TpTestsTextChannelGroup *self = TP_TESTS_TEXT_CHANNEL_GROUP (object); + + tp_message_mixin_finalize (object); + tp_group_mixin_finalize (object); + + tp_clear_pointer (&self->priv->password, g_free); + + ((GObjectClass *) tp_tests_text_channel_group_parent_class)->finalize (object); +} + +static void +channel_close (TpBaseChannel *base) +{ + TpTestsTextChannelGroup *self = TP_TESTS_TEXT_CHANNEL_GROUP (base); + + if (!self->priv->closed) + { + self->priv->closed = TRUE; + tp_svc_channel_emit_closed (self); + } +} + +static void +tp_tests_text_channel_group_class_init (TpTestsTextChannelGroupClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + TpBaseChannelClass *base_class = (TpBaseChannelClass *) klass; + + g_type_class_add_private (klass, sizeof (TpTestsTextChannelGroupPrivate)); + + object_class->constructed = constructed; + object_class->dispose = dispose; + object_class->finalize = finalize; + + base_class->channel_type = TP_IFACE_CHANNEL_TYPE_TEXT; + base_class->target_handle_type = TP_HANDLE_TYPE_NONE; + base_class->get_interfaces = text_channel_group_get_interfaces; + base_class->close = channel_close; + + tp_group_mixin_class_init (object_class, + G_STRUCT_OFFSET (TpTestsTextChannelGroupClass, group_class), add_member, + NULL); + + tp_group_mixin_class_set_remove_with_reason_func (object_class, + remove_with_reason); + + tp_group_mixin_class_allow_self_removal (object_class); + + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (TpTestsTextChannelGroupClass, dbus_properties_class)); + + tp_group_mixin_init_dbus_properties (object_class); + + tp_message_mixin_init_dbus_properties (object_class); +} + +void +tp_tests_text_channel_group_join (TpTestsTextChannelGroup *self) +{ + TpIntset *add, *empty; + GHashTable *details = tp_asv_new ( + "actor", G_TYPE_UINT, 0, + "change-reason", G_TYPE_UINT, 0, + "message", G_TYPE_STRING, "", + NULL); + + /* Add ourself as a member */ + add = tp_intset_new_containing ( + tp_base_connection_get_self_handle (self->conn)); + empty = tp_intset_new (); + + tp_group_mixin_change_members ((GObject *) self, add, empty, + empty, empty, details); + + tp_intset_destroy (add); + tp_intset_destroy (empty); + g_hash_table_unref (details); +} + +void +tp_tests_text_channel_set_password (TpTestsTextChannelGroup *self, + const gchar *password) +{ + gboolean pass_was_needed, pass_needed; + + pass_was_needed = (self->priv->password != NULL); + + tp_clear_pointer (&self->priv->password, g_free); + + self->priv->password = g_strdup (password); + + pass_needed = (self->priv->password != NULL); + + if (pass_needed == pass_was_needed) + return; + + if (pass_needed) + tp_svc_channel_interface_password_emit_password_flags_changed (self, + TP_CHANNEL_PASSWORD_FLAG_PROVIDE, 0); + else + tp_svc_channel_interface_password_emit_password_flags_changed (self, + 0, TP_CHANNEL_PASSWORD_FLAG_PROVIDE); +} + +static void +password_get_password_flags (TpSvcChannelInterfacePassword *chan, + DBusGMethodInvocation *context) +{ + TpTestsTextChannelGroup *self = (TpTestsTextChannelGroup *) chan; + TpChannelPasswordFlags flags = 0; + + if (self->priv->password != NULL) + flags |= TP_CHANNEL_PASSWORD_FLAG_PROVIDE; + + tp_svc_channel_interface_password_return_from_get_password_flags (context, + flags); +} + +static void +password_provide_password (TpSvcChannelInterfacePassword *chan, + const gchar *password, + DBusGMethodInvocation *context) +{ + TpTestsTextChannelGroup *self = (TpTestsTextChannelGroup *) chan; + + tp_svc_channel_interface_password_return_from_provide_password (context, + !tp_strdiff (password, self->priv->password)); +} + +static void +password_iface_init (gpointer iface, gpointer data) +{ + TpSvcChannelInterfacePasswordClass *klass = iface; + +#define IMPLEMENT(x) tp_svc_channel_interface_password_implement_##x (klass, password_##x) + IMPLEMENT (get_password_flags); + IMPLEMENT (provide_password); +#undef IMPLEMENT +} diff --git a/tests/lib/telepathy/contactlist/textchan-group.h b/tests/lib/telepathy/contactlist/textchan-group.h new file mode 100644 index 00000000..810e0048 --- /dev/null +++ b/tests/lib/telepathy/contactlist/textchan-group.h @@ -0,0 +1,72 @@ +/* + * a stub anonymous MUC + * + * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2008 Nokia Corporation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#ifndef __TEST_TEXT_CHANNEL_GROUP_H__ +#define __TEST_TEXT_CHANNEL_GROUP_H__ + +#include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + +G_BEGIN_DECLS + +typedef struct _TpTestsTextChannelGroup TpTestsTextChannelGroup; +typedef struct _TpTestsTextChannelGroupClass TpTestsTextChannelGroupClass; +typedef struct _TpTestsTextChannelGroupPrivate TpTestsTextChannelGroupPrivate; + +GType tp_tests_text_channel_group_get_type (void); + +#define TP_TESTS_TYPE_TEXT_CHANNEL_GROUP \ + (tp_tests_text_channel_group_get_type ()) +#define TP_TESTS_TEXT_CHANNEL_GROUP(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_TEXT_CHANNEL_GROUP, \ + TpTestsTextChannelGroup)) +#define TP_TESTS_TEXT_CHANNEL_GROUP_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_TEXT_CHANNEL_GROUP, \ + TpTestsTextChannelGroupClass)) +#define TEST_IS_TEXT_CHANNEL_GROUP(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_TEXT_CHANNEL_GROUP)) +#define TEST_IS_TEXT_CHANNEL_GROUP_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_TEXT_CHANNEL_GROUP)) +#define TP_TESTS_TEXT_CHANNEL_GROUP_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_TEXT_CHANNEL_GROUP, \ + TpTestsTextChannelGroupClass)) + +struct _TpTestsTextChannelGroupClass { + TpBaseChannelClass parent_class; + + TpGroupMixinClass group_class; + TpDBusPropertiesMixinClass dbus_properties_class; +}; + +struct _TpTestsTextChannelGroup { + TpBaseChannel parent; + + TpBaseConnection *conn; + + TpMessageMixin message; + TpGroupMixin group; + + TpHandle removed_handle; + gchar *removed_message; + TpChannelGroupChangeReason removed_reason; + + TpTestsTextChannelGroupPrivate *priv; +}; + + +void tp_tests_text_channel_group_join (TpTestsTextChannelGroup *self); + +void tp_tests_text_channel_set_password (TpTestsTextChannelGroup *self, + const gchar *password); + +G_END_DECLS + +#endif /* #ifndef __TEST_TEXT_CHANNEL_GROUP_H__ */ diff --git a/tests/lib/telepathy/contactlist/textchan-null.c b/tests/lib/telepathy/contactlist/textchan-null.c deleted file mode 100644 index bbeb0c71..00000000 --- a/tests/lib/telepathy/contactlist/textchan-null.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - * /dev/null as a text channel - * - * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> - * Copyright (C) 2008 Nokia Corporation - * - * Copying and distribution of this file, with or without modification, - * are permitted in any medium without royalty provided the copyright - * notice and this notice are preserved. - */ - -#include "config.h" - -#include "textchan-null.h" - -#include <telepathy-glib/base-connection.h> -#include <telepathy-glib/channel-iface.h> -#include <telepathy-glib/dbus.h> -#include <telepathy-glib/dbus-properties-mixin.h> -#include <telepathy-glib/interfaces.h> -#include <telepathy-glib/svc-channel.h> -#include <telepathy-glib/svc-generic.h> - -/* This is for text-mixin unit tests, others should be using ExampleEcho2Channel - * which uses newer TpMessageMixin */ -G_GNUC_BEGIN_IGNORE_DEPRECATIONS - -static void text_iface_init (gpointer iface, gpointer data); -static void channel_iface_init (gpointer iface, gpointer data); - -G_DEFINE_TYPE_WITH_CODE (TpTestsTextChannelNull, - tp_tests_text_channel_null, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, text_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL)) - -G_DEFINE_TYPE_WITH_CODE (TpTestsPropsTextChannel, - tp_tests_props_text_channel, - TP_TESTS_TYPE_TEXT_CHANNEL_NULL, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, - tp_dbus_properties_mixin_iface_init)) - -G_DEFINE_TYPE_WITH_CODE (TpTestsPropsGroupTextChannel, - tp_tests_props_group_text_channel, - TP_TESTS_TYPE_PROPS_TEXT_CHANNEL, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP, - tp_group_mixin_iface_init)) - -static const char *tp_tests_text_channel_null_interfaces[] = { NULL }; - -/* type definition stuff */ - -enum -{ - PROP_OBJECT_PATH = 1, - PROP_CHANNEL_TYPE, - PROP_HANDLE_TYPE, - PROP_HANDLE, - PROP_TARGET_ID, - PROP_CONNECTION, - PROP_INTERFACES, - PROP_REQUESTED, - PROP_INITIATOR_HANDLE, - PROP_INITIATOR_ID, - N_PROPS -}; - -struct _TpTestsTextChannelNullPrivate -{ - TpBaseConnection *conn; - gchar *object_path; - TpHandle handle; - - unsigned closed:1; - unsigned disposed:1; -}; - -static void -tp_tests_text_channel_null_init (TpTestsTextChannelNull *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - TP_TESTS_TYPE_TEXT_CHANNEL_NULL, TpTestsTextChannelNullPrivate); -} - -static void -tp_tests_props_text_channel_init (TpTestsPropsTextChannel *self) -{ - self->dbus_property_interfaces_retrieved = g_hash_table_new (NULL, NULL); -} - -static GObject * -constructor (GType type, - guint n_props, - GObjectConstructParam *props) -{ - GObject *object = - G_OBJECT_CLASS (tp_tests_text_channel_null_parent_class)->constructor (type, - n_props, props); - TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles - (self->priv->conn, TP_HANDLE_TYPE_CONTACT); - - tp_handle_ref (contact_repo, self->priv->handle); - - tp_dbus_daemon_register_object ( - tp_base_connection_get_dbus_daemon (self->priv->conn), - self->priv->object_path, self); - - tp_text_mixin_init (object, G_STRUCT_OFFSET (TpTestsTextChannelNull, text), - contact_repo); - - tp_text_mixin_set_message_types (object, - TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, - TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION, - TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, - G_MAXUINT); - - return object; -} - -static void -get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); - - switch (property_id) - { - case PROP_OBJECT_PATH: - g_value_set_string (value, self->priv->object_path); - break; - case PROP_CHANNEL_TYPE: - g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TEXT); - break; - case PROP_HANDLE_TYPE: - g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); - break; - case PROP_HANDLE: - g_value_set_uint (value, self->priv->handle); - break; - case PROP_TARGET_ID: - { - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - self->priv->conn, TP_HANDLE_TYPE_CONTACT); - - g_value_set_string (value, - tp_handle_inspect (contact_repo, self->priv->handle)); - } - break; - case PROP_REQUESTED: - g_value_set_boolean (value, TRUE); - break; - case PROP_INITIATOR_HANDLE: - g_value_set_uint (value, tp_base_connection_get_self_handle ( - self->priv->conn)); - break; - case PROP_INITIATOR_ID: - { - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - self->priv->conn, TP_HANDLE_TYPE_CONTACT); - - g_value_set_string (value, - tp_handle_inspect (contact_repo, - tp_base_connection_get_self_handle (self->priv->conn))); - } - break; - case PROP_INTERFACES: - g_value_set_boxed (value, tp_tests_text_channel_null_interfaces); - break; - case PROP_CONNECTION: - g_value_set_object (value, self->priv->conn); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); - - switch (property_id) - { - case PROP_OBJECT_PATH: - g_free (self->priv->object_path); - self->priv->object_path = g_value_dup_string (value); - break; - case PROP_HANDLE: - /* we don't ref it here because we don't necessarily have access to the - * contact repo yet - instead we ref it in the constructor. - */ - self->priv->handle = g_value_get_uint (value); - break; - case PROP_HANDLE_TYPE: - case PROP_CHANNEL_TYPE: - /* these properties are writable in the interface, but not actually - * meaningfully changable on this channel, so we do nothing */ - break; - case PROP_CONNECTION: - self->priv->conn = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -void -tp_tests_text_channel_null_close (TpTestsTextChannelNull *self) -{ - if (!self->priv->closed) - { - self->priv->closed = TRUE; - tp_svc_channel_emit_closed (self); - tp_dbus_daemon_unregister_object ( - tp_base_connection_get_dbus_daemon (self->priv->conn), self); - } -} - -static void -dispose (GObject *object) -{ - TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); - - if (self->priv->disposed) - return; - - self->priv->disposed = TRUE; - tp_tests_text_channel_null_close (self); - - ((GObjectClass *) tp_tests_text_channel_null_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); - TpHandleRepoIface *contact_handles = tp_base_connection_get_handles - (self->priv->conn, TP_HANDLE_TYPE_CONTACT); - - tp_handle_unref (contact_handles, self->priv->handle); - g_free (self->priv->object_path); - - tp_text_mixin_finalize (object); - - ((GObjectClass *) tp_tests_text_channel_null_parent_class)->finalize (object); -} - -static void -tp_tests_text_channel_null_class_init (TpTestsTextChannelNullClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - GParamSpec *param_spec; - - g_type_class_add_private (klass, sizeof (TpTestsTextChannelNullPrivate)); - - object_class->constructor = constructor; - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - g_object_class_override_property (object_class, PROP_OBJECT_PATH, - "object-path"); - g_object_class_override_property (object_class, PROP_CHANNEL_TYPE, - "channel-type"); - g_object_class_override_property (object_class, PROP_HANDLE_TYPE, - "handle-type"); - g_object_class_override_property (object_class, PROP_HANDLE, "handle"); - - param_spec = g_param_spec_object ("connection", "TpBaseConnection object", - "Connection object that owns this channel", - TP_TYPE_BASE_CONNECTION, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); - - param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces", - "Additional Channel.Interface.* interfaces", - G_TYPE_STRV, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); - - param_spec = g_param_spec_string ("target-id", "Peer's ID", - "The string obtained by inspecting the target handle", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec); - - param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle", - "The contact who initiated the channel", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE, - param_spec); - - param_spec = g_param_spec_string ("initiator-id", "Initiator's ID", - "The string obtained by inspecting the initiator-handle", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_INITIATOR_ID, - param_spec); - - param_spec = g_param_spec_boolean ("requested", "Requested?", - "True if this channel was requested by the local user", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_REQUESTED, param_spec); - - tp_text_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpTestsTextChannelNullClass, text_class)); -} - -static void -tp_tests_props_text_channel_getter_gobject_properties (GObject *object, - GQuark interface, - GQuark name, - GValue *value, - gpointer getter_data) -{ - TpTestsPropsTextChannel *self = TP_TESTS_PROPS_TEXT_CHANNEL (object); - - g_hash_table_insert (self->dbus_property_interfaces_retrieved, - GUINT_TO_POINTER (interface), GUINT_TO_POINTER (interface)); - - tp_dbus_properties_mixin_getter_gobject_properties (object, interface, name, - value, getter_data); -} - -static void -props_finalize (GObject *object) -{ - TpTestsPropsTextChannel *self = TP_TESTS_PROPS_TEXT_CHANNEL (object); - - g_hash_table_unref (self->dbus_property_interfaces_retrieved); - - ((GObjectClass *) tp_tests_props_text_channel_parent_class)->finalize (object); -} - -static void -tp_tests_props_text_channel_class_init (TpTestsPropsTextChannelClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - static TpDBusPropertiesMixinPropImpl channel_props[] = { - { "TargetHandleType", "handle-type", NULL }, - { "TargetHandle", "handle", NULL }, - { "ChannelType", "channel-type", NULL }, - { "Interfaces", "interfaces", NULL }, - { "TargetID", "target-id", NULL }, - { "Requested", "requested", NULL }, - { "InitiatorHandle", "initiator-handle", NULL }, - { "InitiatorID", "initiator-id", NULL }, - { NULL } - }; - static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { - { TP_IFACE_CHANNEL, - tp_tests_props_text_channel_getter_gobject_properties, - NULL, - channel_props, - }, - { NULL } - }; - - object_class->finalize = props_finalize; - - klass->dbus_properties_class.interfaces = prop_interfaces; - tp_dbus_properties_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpTestsPropsTextChannelClass, dbus_properties_class)); -} - -static void -tp_tests_props_group_text_channel_init (TpTestsPropsGroupTextChannel *self) -{ -} - -static void -group_constructed (GObject *self) -{ - TpBaseConnection *conn = TP_TESTS_TEXT_CHANNEL_NULL (self)->priv->conn; - void (*chain_up) (GObject *) = - ((GObjectClass *) tp_tests_props_group_text_channel_parent_class)->constructed; - - if (chain_up != NULL) - chain_up (self); - - tp_group_mixin_init (self, - G_STRUCT_OFFSET (TpTestsPropsGroupTextChannel, group), - tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT), - tp_base_connection_get_self_handle (conn)); - tp_group_mixin_change_flags (self, TP_CHANNEL_GROUP_FLAG_PROPERTIES, 0); -} - -static void -group_finalize (GObject *self) -{ - tp_group_mixin_finalize (self); - - ((GObjectClass *) tp_tests_props_group_text_channel_parent_class)->finalize (self); -} - -static gboolean -dummy_add_remove_member (GObject *obj, - TpHandle handle, - const gchar *message, - GError **error) -{ - return TRUE; -} - -static void -group_iface_props_getter (GObject *object, - GQuark interface, - GQuark name, - GValue *value, - gpointer getter_data) -{ - TpTestsPropsTextChannel *self = TP_TESTS_PROPS_TEXT_CHANNEL (object); - - g_hash_table_insert (self->dbus_property_interfaces_retrieved, - GUINT_TO_POINTER (interface), GUINT_TO_POINTER (interface)); - - tp_group_mixin_get_dbus_property (object, interface, name, value, getter_data); -} - -static void -tp_tests_props_group_text_channel_class_init (TpTestsPropsGroupTextChannelClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - static TpDBusPropertiesMixinPropImpl group_props[] = { - { "GroupFlags", NULL, NULL }, - { "HandleOwners", NULL, NULL }, - { "LocalPendingMembers", NULL, NULL }, - { "Members", NULL, NULL }, - { "RemotePendingMembers", NULL, NULL }, - { "SelfHandle", NULL, NULL }, - { NULL } - }; - - object_class->constructed = group_constructed; - object_class->finalize = group_finalize; - - tp_group_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpTestsPropsGroupTextChannelClass, group_class), - dummy_add_remove_member, - dummy_add_remove_member); - tp_dbus_properties_mixin_implement_interface (object_class, - TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP, group_iface_props_getter, NULL, - group_props); -} - -static void -channel_close (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface); - - tp_tests_text_channel_null_close (self); - tp_svc_channel_return_from_close (context); -} - -static void -channel_get_channel_type (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface); - - self->get_channel_type_called++; - - tp_svc_channel_return_from_get_channel_type (context, - TP_IFACE_CHANNEL_TYPE_TEXT); -} - -static void -channel_get_handle (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface); - - self->get_handle_called++; - - tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT, - self->priv->handle); -} - -static void -channel_get_interfaces (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface); - - self->get_interfaces_called++; - - tp_svc_channel_return_from_get_interfaces (context, - tp_tests_text_channel_null_interfaces); -} - -static void -channel_iface_init (gpointer iface, - gpointer data) -{ - TpSvcChannelClass *klass = iface; - -#define IMPLEMENT(x) tp_svc_channel_implement_##x (klass, channel_##x) - IMPLEMENT (close); - IMPLEMENT (get_channel_type); - IMPLEMENT (get_handle); - IMPLEMENT (get_interfaces); -#undef IMPLEMENT -} - -static void -text_send (TpSvcChannelTypeText *iface, - guint type, - const gchar *text, - DBusGMethodInvocation *context) -{ - /* silently swallow the message */ - tp_svc_channel_type_text_return_from_send (context); -} - -static void -text_iface_init (gpointer iface, - gpointer data) -{ - TpSvcChannelTypeTextClass *klass = iface; - - tp_text_mixin_iface_init (iface, data); -#define IMPLEMENT(x) tp_svc_channel_type_text_implement_##x (klass, text_##x) - IMPLEMENT (send); -#undef IMPLEMENT -} - -GHashTable * -tp_tests_text_channel_get_props (TpTestsTextChannelNull *self) -{ - GHashTable *props; - TpHandleType handle_type; - TpHandle handle; - gchar *target_id; - gboolean requested; - TpHandle initiator_handle; - gchar *initiator_id; - GStrv interfaces; - - g_object_get (self, - "handle-type", &handle_type, - "handle", &handle, - "target-id", &target_id, - "requested", &requested, - "initiator-handle", &initiator_handle, - "initiator-id", &initiator_id, - "interfaces", &interfaces, - NULL); - - props = tp_asv_new ( - TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT, - TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, handle_type, - TP_PROP_CHANNEL_TARGET_HANDLE, G_TYPE_UINT, handle, - TP_PROP_CHANNEL_TARGET_ID, G_TYPE_STRING, target_id, - TP_PROP_CHANNEL_REQUESTED, G_TYPE_BOOLEAN, requested, - TP_PROP_CHANNEL_INITIATOR_HANDLE, G_TYPE_UINT, initiator_handle, - TP_PROP_CHANNEL_INITIATOR_ID, G_TYPE_STRING, initiator_id, - TP_PROP_CHANNEL_INTERFACES, G_TYPE_STRV, interfaces, - NULL); - - g_free (target_id); - g_free (initiator_id); - g_strfreev (interfaces); - return props; -} - -G_GNUC_END_IGNORE_DEPRECATIONS diff --git a/tests/lib/telepathy/contactlist/textchan-null.h b/tests/lib/telepathy/contactlist/textchan-null.h deleted file mode 100644 index 583bec57..00000000 --- a/tests/lib/telepathy/contactlist/textchan-null.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * /dev/null as a text channel - * - * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> - * Copyright (C) 2008 Nokia Corporation - * - * Copying and distribution of this file, with or without modification, - * are permitted in any medium without royalty provided the copyright - * notice and this notice are preserved. - */ - -#ifndef __TP_TESTS_TEXT_CHANNEL_NULL_H__ -#define __TP_TESTS_TEXT_CHANNEL_NULL_H__ - -#include <glib-object.h> -#include <telepathy-glib/base-connection.h> -#include <telepathy-glib/text-mixin.h> -#include <telepathy-glib/group-mixin.h> - -G_BEGIN_DECLS - -typedef struct _TpTestsTextChannelNull TpTestsTextChannelNull; -typedef struct _TpTestsTextChannelNullClass TpTestsTextChannelNullClass; -typedef struct _TpTestsTextChannelNullPrivate TpTestsTextChannelNullPrivate; - -GType tp_tests_text_channel_null_get_type (void); - -#define TP_TESTS_TYPE_TEXT_CHANNEL_NULL \ - (tp_tests_text_channel_null_get_type ()) -#define TP_TESTS_TEXT_CHANNEL_NULL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_TEXT_CHANNEL_NULL, \ - TpTestsTextChannelNull)) -#define TP_TESTS_TEXT_CHANNEL_NULL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_TEXT_CHANNEL_NULL, \ - TpTestsTextChannelNullClass)) -#define TP_TESTS_IS_TEXT_CHANNEL_NULL(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_TEXT_CHANNEL_NULL)) -#define TP_TESTS_IS_TEXT_CHANNEL_NULL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_TEXT_CHANNEL_NULL)) -#define TP_TESTS_TEXT_CHANNEL_NULL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_TEXT_CHANNEL_NULL, \ - TpTestsTextChannelNullClass)) - -struct _TpTestsTextChannelNullClass { - GObjectClass parent_class; - - TpTextMixinClass text_class; -}; - -struct _TpTestsTextChannelNull { - GObject parent; - TpTextMixin text; - - guint get_handle_called; - guint get_interfaces_called; - guint get_channel_type_called; - - TpTestsTextChannelNullPrivate *priv; -}; - -/* Subclass with D-Bus properties */ - -typedef struct _TestPropsTextChannel TpTestsPropsTextChannel; -typedef struct _TestPropsTextChannelClass TpTestsPropsTextChannelClass; - -struct _TestPropsTextChannel { - TpTestsTextChannelNull parent; - - GHashTable *dbus_property_interfaces_retrieved; -}; - -struct _TestPropsTextChannelClass { - TpTestsTextChannelNullClass parent; - - TpDBusPropertiesMixinClass dbus_properties_class; -}; - -GType tp_tests_props_text_channel_get_type (void); - -#define TP_TESTS_TYPE_PROPS_TEXT_CHANNEL \ - (tp_tests_props_text_channel_get_type ()) -#define TP_TESTS_PROPS_TEXT_CHANNEL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL, \ - TpTestsPropsTextChannel)) -#define TP_TESTS_PROPS_TEXT_CHANNEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL, \ - TpTestsPropsTextChannelClass)) -#define TP_TESTS_IS_PROPS_TEXT_CHANNEL(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL)) -#define TP_TESTS_IS_PROPS_TEXT_CHANNEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL)) -#define TP_TESTS_PROPS_TEXT_CHANNEL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_PROPS_TEXT_CHANNEL, \ - TpTestsPropsTextChannelClass)) - -/* Subclass with D-Bus properties and Group */ - -typedef struct _TestPropsGroupTextChannel TpTestsPropsGroupTextChannel; -typedef struct _TestPropsGroupTextChannelClass TpTestsPropsGroupTextChannelClass; - -struct _TestPropsGroupTextChannel { - TpTestsPropsTextChannel parent; - - TpGroupMixin group; -}; - -struct _TestPropsGroupTextChannelClass { - TpTestsPropsTextChannelClass parent; - - TpGroupMixinClass group_class; -}; - -GType tp_tests_props_group_text_channel_get_type (void); - -#define TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL \ - (tp_tests_props_group_text_channel_get_type ()) -#define TP_TESTS_PROPS_GROUP_TEXT_CHANNEL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL, \ - TpTestsPropsGroupTextChannel)) -#define TP_TESTS_PROPS_GROUP_TEXT_CHANNEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL, \ - TpTestsPropsGroupTextChannelClass)) -#define TP_TESTS_IS_PROPS_GROUP_TEXT_CHANNEL(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL)) -#define TP_TESTS_IS_PROPS_GROUP_TEXT_CHANNEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL)) -#define TP_TESTS_PROPS_GROUP_TEXT_CHANNEL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_PROPS_GROUP_TEXT_CHANNEL, \ - TpTestsPropsGroupTextChannelClass)) - -void tp_tests_text_channel_null_close (TpTestsTextChannelNull *self); - -GHashTable * tp_tests_text_channel_get_props (TpTestsTextChannelNull *self); - -G_END_DECLS - -#endif /* #ifndef __TP_TESTS_TEXT_CHANNEL_NULL_H__ */ diff --git a/tests/lib/telepathy/contactlist/tls-certificate.c b/tests/lib/telepathy/contactlist/tls-certificate.c new file mode 100644 index 00000000..0da16456 --- /dev/null +++ b/tests/lib/telepathy/contactlist/tls-certificate.c @@ -0,0 +1,350 @@ +/* + * tls-certificate.c - Source for TpTestsTLSCertificate + * Copyright (C) 2010 Collabora Ltd. + * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "tls-certificate.h" + +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> + +#define DEBUG_FLAG TP_TESTS_DEBUG_TLS +#include "debug.h" + +static void +tls_certificate_iface_init (gpointer g_iface, gpointer iface_data); + +G_DEFINE_TYPE_WITH_CODE (TpTestsTLSCertificate, + tp_tests_tls_certificate, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_AUTHENTICATION_TLS_CERTIFICATE, + tls_certificate_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init);) + +struct _TpTestsTLSCertificatePrivate { + gchar *object_path; + + gchar *cert_type; + TpTLSCertificateState cert_state; + + GPtrArray *rejections; + GPtrArray *cert_data; + + TpDBusDaemon *daemon; + + gboolean dispose_has_run; +}; + +enum { + PROP_OBJECT_PATH = 1, + PROP_STATE, + PROP_REJECTIONS, + PROP_CERTIFICATE_TYPE, + PROP_CERTIFICATE_CHAIN_DATA, + + /* not exported */ + PROP_DBUS_DAEMON, + + NUM_PROPERTIES +}; + +static void +tp_tests_tls_certificate_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + TpTestsTLSCertificate *self = TP_TESTS_TLS_CERTIFICATE (object); + + switch (property_id) + { + case PROP_OBJECT_PATH: + g_value_set_string (value, self->priv->object_path); + break; + case PROP_STATE: + g_value_set_uint (value, self->priv->cert_state); + break; + case PROP_REJECTIONS: + g_value_set_boxed (value, self->priv->rejections); + break; + case PROP_CERTIFICATE_TYPE: + g_value_set_string (value, self->priv->cert_type); + break; + case PROP_CERTIFICATE_CHAIN_DATA: + g_value_set_boxed (value, self->priv->cert_data); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +tp_tests_tls_certificate_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + TpTestsTLSCertificate *self = TP_TESTS_TLS_CERTIFICATE (object); + + switch (property_id) + { + case PROP_OBJECT_PATH: + self->priv->object_path = g_value_dup_string (value); + break; + case PROP_CERTIFICATE_TYPE: + self->priv->cert_type = g_value_dup_string (value); + break; + case PROP_CERTIFICATE_CHAIN_DATA: + self->priv->cert_data = g_value_dup_boxed (value); + break; + case PROP_DBUS_DAEMON: + self->priv->daemon = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, value); + break; + } +} + +static void +tp_tests_tls_certificate_finalize (GObject *object) +{ + TpTestsTLSCertificate *self = TP_TESTS_TLS_CERTIFICATE (object); + + tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, + &self->priv->rejections); + + g_free (self->priv->object_path); + g_free (self->priv->cert_type); + g_ptr_array_unref (self->priv->cert_data); + + G_OBJECT_CLASS (tp_tests_tls_certificate_parent_class)->finalize (object); +} + +static void +tp_tests_tls_certificate_dispose (GObject *object) +{ + TpTestsTLSCertificate *self = TP_TESTS_TLS_CERTIFICATE (object); + + if (self->priv->dispose_has_run) + return; + + self->priv->dispose_has_run = TRUE; + + tp_clear_object (&self->priv->daemon); + + G_OBJECT_CLASS (tp_tests_tls_certificate_parent_class)->dispose (object); +} + +static void +tp_tests_tls_certificate_constructed (GObject *object) +{ + TpTestsTLSCertificate *self = TP_TESTS_TLS_CERTIFICATE (object); + void (*chain_up) (GObject *) = + G_OBJECT_CLASS (tp_tests_tls_certificate_parent_class)->constructed; + + if (chain_up != NULL) + chain_up (object); + + /* register the certificate on the bus */ + tp_dbus_daemon_register_object (self->priv->daemon, + self->priv->object_path, self); +} + +static void +tp_tests_tls_certificate_init (TpTestsTLSCertificate *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + TP_TESTS_TYPE_TLS_CERTIFICATE, TpTestsTLSCertificatePrivate); + self->priv->rejections = g_ptr_array_new (); +} + +static void +tp_tests_tls_certificate_class_init (TpTestsTLSCertificateClass *klass) +{ + static TpDBusPropertiesMixinPropImpl object_props[] = { + { "State", "state", NULL }, + { "Rejections", "rejections", NULL }, + { "CertificateType", "certificate-type", NULL }, + { "CertificateChainData", "certificate-chain-data", NULL }, + { NULL } + }; + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { TP_IFACE_AUTHENTICATION_TLS_CERTIFICATE, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + object_props, + }, + { NULL } + }; + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + g_type_class_add_private (klass, sizeof (TpTestsTLSCertificatePrivate)); + + oclass->finalize = tp_tests_tls_certificate_finalize; + oclass->dispose = tp_tests_tls_certificate_dispose; + oclass->set_property = tp_tests_tls_certificate_set_property; + oclass->get_property = tp_tests_tls_certificate_get_property; + oclass->constructed = tp_tests_tls_certificate_constructed; + + pspec = g_param_spec_string ("object-path", + "D-Bus object path", + "The D-Bus object path used for this object on the bus.", + NULL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_OBJECT_PATH, pspec); + + pspec = g_param_spec_uint ("state", + "State of this certificate", + "The state of this TLS certificate.", + 0, TP_NUM_TLS_CERTIFICATE_STATES - 1, + TP_TLS_CERTIFICATE_STATE_PENDING, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_STATE, pspec); + + pspec = g_param_spec_boxed ("rejections", + "The reject reasons", + "The reasons why this TLS certificate has been rejected", + TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_REJECTIONS, pspec); + + pspec = g_param_spec_string ("certificate-type", + "The certificate type", + "The type of this certificate.", + NULL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_CERTIFICATE_TYPE, pspec); + + pspec = g_param_spec_boxed ("certificate-chain-data", + "The certificate chain data", + "The raw PEM-encoded trust chain of this certificate.", + TP_ARRAY_TYPE_UCHAR_ARRAY_LIST, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_CERTIFICATE_CHAIN_DATA, pspec); + + pspec = g_param_spec_object ("dbus-daemon", + "The DBus daemon connection", + "The connection to the DBus daemon owning the CM", + TP_TYPE_DBUS_DAEMON, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_DBUS_DAEMON, pspec); + + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (oclass, + G_STRUCT_OFFSET (TpTestsTLSCertificateClass, dbus_props_class)); +} + +static void +tp_tests_tls_certificate_accept (TpSvcAuthenticationTLSCertificate *cert, + DBusGMethodInvocation *context) +{ + TpTestsTLSCertificate *self = TP_TESTS_TLS_CERTIFICATE (cert); + + DEBUG ("Accept() called on the TLS certificate; current state %u", + self->priv->cert_state); + + if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING) + { + GError error = + { TP_ERROR, + TP_ERROR_INVALID_ARGUMENT, + "Calling Accept() on a certificate with state != PENDING " + "doesn't make sense." + }; + + dbus_g_method_return_error (context, &error); + return; + } + + self->priv->cert_state = TP_TLS_CERTIFICATE_STATE_ACCEPTED; + tp_svc_authentication_tls_certificate_emit_accepted (self); + + tp_svc_authentication_tls_certificate_return_from_accept (context); +} + +static void +tp_tests_tls_certificate_reject (TpSvcAuthenticationTLSCertificate *cert, + const GPtrArray *rejections, + DBusGMethodInvocation *context) +{ + TpTestsTLSCertificate *self = TP_TESTS_TLS_CERTIFICATE (cert); + + DEBUG ("Reject() called on the TLS certificate with rejections %p, " + "length %u; current state %u", rejections, rejections->len, + self->priv->cert_state); + + if (rejections->len < 1) + { + GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Calling Reject() with a zero-length rejection list." }; + + dbus_g_method_return_error (context, &error); + return; + } + + if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING) + { + GError error = + { TP_ERROR, + TP_ERROR_INVALID_ARGUMENT, + "Calling Reject() on a certificate with state != PENDING " + "doesn't make sense." + }; + + dbus_g_method_return_error (context, &error); + return; + } + + tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, + &self->priv->rejections); + + self->priv->rejections = + g_boxed_copy (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, + rejections); + self->priv->cert_state = TP_TLS_CERTIFICATE_STATE_REJECTED; + + tp_svc_authentication_tls_certificate_emit_rejected ( + self, self->priv->rejections); + + tp_svc_authentication_tls_certificate_return_from_reject (context); +} + +static void +tls_certificate_iface_init (gpointer g_iface, + gpointer iface_data) +{ + TpSvcAuthenticationTLSCertificateClass *klass = g_iface; + +#define IMPLEMENT(x) \ + tp_svc_authentication_tls_certificate_implement_##x ( \ + klass, tp_tests_tls_certificate_##x) + IMPLEMENT (accept); + IMPLEMENT (reject); +#undef IMPLEMENT +} + +void +tp_tests_tls_certificate_clear_rejection (TpTestsTLSCertificate *self) +{ + g_ptr_array_set_size (self->priv->rejections, 0); +} diff --git a/tests/lib/telepathy/contactlist/tls-certificate.h b/tests/lib/telepathy/contactlist/tls-certificate.h new file mode 100644 index 00000000..1de31927 --- /dev/null +++ b/tests/lib/telepathy/contactlist/tls-certificate.h @@ -0,0 +1,68 @@ +/* + * tls-certificate.h - Header for TpTestsTLSCertificate + * Copyright (C) 2010 Collabora Ltd. + * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __TP_TESTS_TLS_CERTIFICATE_H__ +#define __TP_TESTS_TLS_CERTIFICATE_H__ + +#include <glib-object.h> + +#include <telepathy-glib/telepathy-glib.h> + +G_BEGIN_DECLS + +typedef struct _TpTestsTLSCertificate TpTestsTLSCertificate; +typedef struct _TpTestsTLSCertificateClass TpTestsTLSCertificateClass; +typedef struct _TpTestsTLSCertificatePrivate TpTestsTLSCertificatePrivate; + +struct _TpTestsTLSCertificateClass { + GObjectClass parent_class; + + TpDBusPropertiesMixinClass dbus_props_class; +}; + +struct _TpTestsTLSCertificate { + GObject parent; + + TpTestsTLSCertificatePrivate *priv; +}; + +GType tp_tests_tls_certificate_get_type (void); + +#define TP_TESTS_TYPE_TLS_CERTIFICATE \ + (tp_tests_tls_certificate_get_type ()) +#define TP_TESTS_TLS_CERTIFICATE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_TLS_CERTIFICATE, \ + TpTestsTLSCertificate)) +#define TP_TESTS_TLS_CERTIFICATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_TLS_CERTIFICATE, \ + TpTestsTLSCertificateClass)) +#define TP_TESTS_IS_TLS_CERTIFICATE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_TLS_CERTIFICATE)) +#define TP_TESTS_IS_TLS_CERTIFICATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_TLS_CERTIFICATE)) +#define TP_TESTS_TLS_CERTIFICATE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_TLS_CERTIFICATE, \ + TpTestsTLSCertificateClass)) + +void tp_tests_tls_certificate_clear_rejection (TpTestsTLSCertificate *self); + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_TLS_CERTIFICATE_H__*/ diff --git a/tests/lib/telepathy/contactlist/tp-test-contactlist.deps b/tests/lib/telepathy/contactlist/tp-test-contactlist.deps index 0d850c28..6e998cee 100644 --- a/tests/lib/telepathy/contactlist/tp-test-contactlist.deps +++ b/tests/lib/telepathy/contactlist/tp-test-contactlist.deps @@ -2,4 +2,4 @@ gio-2.0 dbus-glib-1 gobject-2.0 gio-2.0 -telepathy-glib +telepathy-glib-1 diff --git a/tests/lib/telepathy/contactlist/util.c b/tests/lib/telepathy/contactlist/util.c index 21d38550..792afb9b 100644 --- a/tests/lib/telepathy/contactlist/util.c +++ b/tests/lib/telepathy/contactlist/util.c @@ -12,7 +12,8 @@ #include "util.h" -#include <telepathy-glib/connection.h> +#include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include <glib/gstdio.h> #include <string.h> @@ -176,6 +177,26 @@ _tp_tests_assert_strv_equals (const char *file, } void +_tp_tests_assert_bytes_equal (const gchar *file, int line, + GBytes *actual, gconstpointer expected_data, + gsize expected_length) +{ + if (expected_length != g_bytes_get_size (actual)) + { + g_error ("%s:%d: assertion failed: expected %"G_GSIZE_FORMAT + " bytes, got %"G_GSIZE_FORMAT, + file, line, expected_length, g_bytes_get_size (actual)); + } + else if (memcmp (g_bytes_get_data (actual, NULL), + expected_data, expected_length) != 0) + { + g_error ( + "%s:%d: assertion failed: expected data didn't match the actual data", + file, line); + } +} + +void tp_tests_create_conn (GType conn_type, const gchar *account, gboolean connect, @@ -183,7 +204,6 @@ tp_tests_create_conn (GType conn_type, TpConnection **client_conn) { TpDBusDaemon *dbus; - TpSimpleClientFactory *factory; gchar *name; gchar *conn_path; GError *error = NULL; @@ -192,7 +212,6 @@ tp_tests_create_conn (GType conn_type, g_assert (client_conn != NULL); dbus = tp_tests_dbus_daemon_dup_or_die (); - factory = (TpSimpleClientFactory *) tp_automatic_client_factory_new (dbus); *service_conn = tp_tests_object_new_static_class ( conn_type, @@ -205,8 +224,7 @@ tp_tests_create_conn (GType conn_type, &name, &conn_path, &error)); g_assert_no_error (error); - *client_conn = tp_simple_client_factory_ensure_connection (factory, - conn_path, NULL, &error); + *client_conn = tp_tests_connection_new (dbus, NULL, conn_path, &error); g_assert (*client_conn != NULL); g_assert_no_error (error); @@ -222,7 +240,6 @@ tp_tests_create_conn (GType conn_type, g_free (conn_path); g_object_unref (dbus); - g_object_unref (factory); } void @@ -318,6 +335,7 @@ _tp_create_local_socket (TpSocketAddressType address_type, TpSocketAccessControl access_control, GSocketService **service, gchar **unix_address, + gchar **unix_tmpdir, GError **error) { gboolean success; @@ -343,7 +361,20 @@ _tp_create_local_socket (TpSocketAddressType address_type, #ifdef HAVE_GIO_UNIX case TP_SOCKET_ADDRESS_TYPE_UNIX: { - address = g_unix_socket_address_new (tmpnam (NULL)); + GError *e = NULL; + gchar *dir = g_dir_make_tmp ("tp-glib-tests.XXXXXX", &e); + gchar *name; + + g_assert_no_error (e); + + name = g_build_filename (dir, "s", NULL); + address = g_unix_socket_address_new (name); + g_free (name); + + if (unix_tmpdir != NULL) + *unix_tmpdir = dir; + else + g_free (dir); break; } #endif @@ -450,12 +481,11 @@ one_contact_cb (GObject *object, TpContact * tp_tests_connection_run_until_contact_by_id (TpConnection *connection, const gchar *id, - guint n_features, - const TpContactFeature *features) + const GQuark *features) { TpContact *contact = NULL; - tp_connection_dup_contact_by_id_async (connection, id, n_features, features, + tp_connection_dup_contact_by_id_async (connection, id, features, one_contact_cb, &contact); while (contact == NULL) @@ -463,3 +493,160 @@ tp_tests_connection_run_until_contact_by_id (TpConnection *connection, return contact; } + +void +tp_tests_channel_assert_expect_members (TpChannel *channel, + TpIntset *expected_members) +{ + GPtrArray *contacts; + TpIntset *members; + guint i; + + members = tp_intset_new (); + contacts = tp_channel_group_dup_members (channel); + if (contacts != NULL) + { + for (i = 0; i < contacts->len; i++) + { + TpContact *contact = g_ptr_array_index (contacts, i); + tp_intset_add (members, tp_contact_get_handle (contact)); + } + } + + g_assert (tp_intset_is_equal (members, expected_members)); + + g_ptr_array_unref (contacts); + tp_intset_destroy (members); +} + +TpConnection * +tp_tests_connection_new (TpDBusDaemon *dbus, + const gchar *bus_name, + const gchar *object_path, + GError **error) +{ + TpClientFactory *factory; + gchar *dup_path = NULL; + TpConnection *ret = NULL; + + g_return_val_if_fail (TP_IS_DBUS_DAEMON (dbus), NULL); + g_return_val_if_fail (object_path != NULL || + (bus_name != NULL && bus_name[0] != ':'), NULL); + + if (object_path == NULL) + { + dup_path = g_strdelimit (g_strdup_printf ("/%s", bus_name), ".", '/'); + object_path = dup_path; + } + + if (!tp_dbus_check_valid_object_path (object_path, error)) + goto finally; + + factory = tp_automatic_client_factory_new (dbus); + ret = tp_client_factory_ensure_connection (factory, + object_path, NULL, error); + g_object_unref (factory); + +finally: + g_free (dup_path); + + return ret; +} + +TpAccount * +tp_tests_account_new (TpDBusDaemon *dbus, + const gchar *object_path, + GError **error) +{ + TpClientFactory *factory; + TpAccount *ret; + + if (!tp_dbus_check_valid_object_path (object_path, error)) + return NULL; + + factory = tp_automatic_client_factory_new (dbus); + ret = tp_client_factory_ensure_account (factory, + object_path, NULL, error); + g_object_unref (factory); + + return ret; +} + +TpChannel * +tp_tests_channel_new (TpConnection *conn, + const gchar *object_path, + const gchar *optional_channel_type, + TpHandleType optional_handle_type, + TpHandle optional_handle, + GError **error) +{ + TpChannel *ret; + GHashTable *asv; + + asv = tp_asv_new (NULL, NULL); + + if (optional_channel_type != NULL) + { + tp_asv_set_string (asv, + TP_PROP_CHANNEL_CHANNEL_TYPE, optional_channel_type); + } + if (optional_handle_type != TP_HANDLE_TYPE_NONE) + { + tp_asv_set_uint32 (asv, + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, optional_handle_type); + } + if (optional_handle != 0) + { + tp_asv_set_uint32 (asv, + TP_PROP_CHANNEL_TARGET_HANDLE, optional_handle); + } + + ret = tp_tests_channel_new_from_properties (conn, object_path, asv, error); + + g_hash_table_unref (asv); + + return ret; +} + +TpChannel * +tp_tests_channel_new_from_properties (TpConnection *conn, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error) +{ + TpClientFactory *factory; + + if (!tp_dbus_check_valid_object_path (object_path, error)) + return NULL; + + factory = tp_proxy_get_factory (conn); + return tp_client_factory_ensure_channel (factory, conn, + object_path, immutable_properties, error); +} + +void +tp_tests_add_channel_to_ptr_array (GPtrArray *arr, + TpChannel *channel) +{ + GValueArray *tmp; + GVariant *variant; + GValue v = G_VALUE_INIT; + GHashTable *asv; + + g_assert (arr != NULL); + g_assert (channel != NULL); + + variant = tp_channel_dup_immutable_properties (channel); + dbus_g_value_parse_g_variant (variant, &v); + asv = g_value_get_boxed (&v); + + tmp = tp_value_array_build (2, + DBUS_TYPE_G_OBJECT_PATH, tp_proxy_get_object_path (channel), + TP_HASH_TYPE_STRING_VARIANT_MAP, asv, + G_TYPE_INVALID); + + g_ptr_array_add (arr, tmp); + g_variant_unref (variant); + g_value_unset (&v); +} + diff --git a/tests/lib/telepathy/contactlist/util.h b/tests/lib/telepathy/contactlist/util.h index d58138ea..3797f854 100644 --- a/tests/lib/telepathy/contactlist/util.h +++ b/tests/lib/telepathy/contactlist/util.h @@ -12,7 +12,6 @@ #define __TP_TESTS_LIB_UTIL_H__ #include <telepathy-glib/telepathy-glib.h> -#include <telepathy-glib/base-connection.h> TpDBusDaemon *tp_tests_dbus_daemon_dup_or_die (void); @@ -36,6 +35,12 @@ void _tp_tests_assert_strv_equals (const char *file, int line, const char *actual_desc, gconstpointer actual_strv, const char *expected_desc, gconstpointer expected_strv); +#define tp_tests_assert_bytes_equals(actual, expected, expected_length) \ + _tp_tests_assert_bytes_equal (__FILE__, __LINE__, \ + actual, expected, expected_length) +void _tp_tests_assert_bytes_equal (const gchar *file, int line, + GBytes *actual, gconstpointer expected_data, gsize expected_length); + void tp_tests_create_conn (GType conn_type, const gchar *account, gboolean connect, @@ -63,6 +68,7 @@ GValue *_tp_create_local_socket (TpSocketAddressType address_type, TpSocketAccessControl access_control, GSocketService **service, gchar **unix_address, + gchar **unix_tmpdir, GError **error); void _tp_destroy_socket_control_list (gpointer data); @@ -72,7 +78,33 @@ void tp_tests_connection_assert_disconnect_succeeds (TpConnection *connection); TpContact *tp_tests_connection_run_until_contact_by_id ( TpConnection *connection, const gchar *id, - guint n_features, - const TpContactFeature *features); + const GQuark *features); + +void tp_tests_channel_assert_expect_members (TpChannel *channel, + TpIntset *expected_members); + +TpConnection *tp_tests_connection_new (TpDBusDaemon *dbus, + const gchar *bus_name, + const gchar *object_path, + GError **error); + +TpAccount *tp_tests_account_new (TpDBusDaemon *dbus, + const gchar *object_path, + GError **error); + +TpChannel *tp_tests_channel_new (TpConnection *conn, + const gchar *object_path, + const gchar *optional_channel_type, + TpHandleType optional_handle_type, + TpHandle optional_handle, + GError **error); + +TpChannel *tp_tests_channel_new_from_properties (TpConnection *conn, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error); + +void tp_tests_add_channel_to_ptr_array (GPtrArray *arr, + TpChannel *channel); #endif /* #ifndef __TP_TESTS_LIB_UTIL_H__ */ diff --git a/tests/lib/telepathy/tpf-test.deps b/tests/lib/telepathy/tpf-test.deps index 1bce19e6..87e45fca 100644 --- a/tests/lib/telepathy/tpf-test.deps +++ b/tests/lib/telepathy/tpf-test.deps @@ -3,5 +3,5 @@ gobject-2.0 gio-2.0 gee-0.8 folks -telepathy-glib +telepathy-glib-1 tp-test-contactlist diff --git a/tests/telepathy/Makefile.am b/tests/telepathy/Makefile.am index 5eda26d5..f7abebed 100644 --- a/tests/telepathy/Makefile.am +++ b/tests/telepathy/Makefile.am @@ -52,7 +52,7 @@ AM_VALAFLAGS += \ --pkg gio-2.0 \ --pkg gee-0.8 \ --pkg gmodule-2.0 \ - --pkg telepathy-glib \ + --pkg telepathy-glib-1 \ --pkg folks \ --pkg folks-telepathy \ --pkg folks-test \ diff --git a/tests/telepathy/individual-properties.vala b/tests/telepathy/individual-properties.vala index 5351824e..2d8215a9 100644 --- a/tests/telepathy/individual-properties.vala +++ b/tests/telepathy/individual-properties.vala @@ -29,7 +29,7 @@ public class IndividualPropertiesTests : TpfTest.TestCase private HashSet<string>? _changes_pending = null; private static string iid_prefix = - "telepathy:/org/freedesktop/Telepathy/Account/cm/protocol/account:"; + "telepathy:/im/telepathy1/Account/cm/protocol/account:"; private string olivier_sha1 = Checksum.compute_for_string (ChecksumType.SHA1, iid_prefix + "olivier@example.com"); diff --git a/tests/telepathy/individual-retrieval.vala b/tests/telepathy/individual-retrieval.vala index 5908c058..8a629a51 100644 --- a/tests/telepathy/individual-retrieval.vala +++ b/tests/telepathy/individual-retrieval.vala @@ -29,7 +29,7 @@ public class IndividualRetrievalTests : TpfTest.TestCase private HashSet<string> default_individuals; private static string iid_prefix = - "telepathy:/org/freedesktop/Telepathy/Account/cm/protocol/account:"; + "telepathy:/im/telepathy1/Account/cm/protocol/account:"; public IndividualRetrievalTests () { diff --git a/tests/tools/manager-file.py b/tests/tools/manager-file.py index 45f64040..a97a1660 100755 --- a/tests/tools/manager-file.py +++ b/tests/tools/manager-file.py @@ -88,8 +88,8 @@ gflags = { def write_manager(f, manager, protos): # pointless backwards compat section print >> f, '[ConnectionManager]' - print >> f, 'BusName=org.freedesktop.Telepathy.ConnectionManager.' + manager - print >> f, 'ObjectPath=/org/freedesktop/Telepathy/ConnectionManager/' + manager + print >> f, 'BusName=im.telepathy1.ConnectionManager.' + manager + print >> f, 'ObjectPath=/im/telepathy1/ConnectionManager/' + manager # protocols for proto, params in protos.iteritems(): diff --git a/tools/import-pidgin.vala b/tools/import-pidgin.vala index f09e6939..cbb25a26 100644 --- a/tools/import-pidgin.vala +++ b/tools/import-pidgin.vala @@ -273,7 +273,7 @@ public class Folks.Importers.Pidgin : Folks.Importer * http://telepathy.freedesktop.org/spec/Connection_Manager.html#Protocol * and http://developer.pidgin.im/wiki/prpl_id. */ if (tp_protocol == "bonjour") - tp_protocol = "local-xmpp"; + tp_protocol = "local_xmpp"; else if (tp_protocol == "novell") tp_protocol = "groupwise"; else if (tp_protocol == "gg") |