diff options
author | Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> | 2011-12-19 13:44:08 -0200 |
---|---|---|
committer | Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> | 2011-12-19 13:44:11 -0200 |
commit | 61c6769b263bff1667466e7e3b4c6d3afc06b5ab (patch) | |
tree | 3cf88437b851b28dbeb7744bd44b60d15b69d4e2 /tests | |
parent | db28c27a556f067255a733a3c66213cb1ee5a5b5 (diff) | |
parent | 8364f3c131e7f132c719331847005df895bdb437 (diff) |
Merge branch 'conn-addressing'
Reviewed-by: Olli Salli (oggis) <olli.salli@collabora.co.uk>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/dbus/CMakeLists.txt | 4 | ||||
-rw-r--r-- | tests/dbus/conn-addressing.cpp | 403 | ||||
-rw-r--r-- | tests/dbus/contacts.cpp | 3 | ||||
-rw-r--r-- | tests/lib/glib/CMakeLists.txt | 3 | ||||
-rw-r--r-- | tests/lib/glib/future/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/lib/glib/future/conn-addressing/CMakeLists.txt | 14 | ||||
-rw-r--r-- | tests/lib/glib/future/conn-addressing/conn.c | 359 | ||||
-rw-r--r-- | tests/lib/glib/future/conn-addressing/conn.h | 57 | ||||
-rw-r--r-- | tests/lib/glib/future/extensions/CMakeLists.txt | 5 | ||||
-rw-r--r-- | tests/lib/glib/future/extensions/all.xml | 1 | ||||
-rw-r--r-- | tests/lib/glib/future/extensions/connection.xml | 9 | ||||
-rw-r--r-- | tests/lib/glib/future/extensions/extensions.h | 2 |
12 files changed, 859 insertions, 2 deletions
diff --git a/tests/dbus/CMakeLists.txt b/tests/dbus/CMakeLists.txt index 16f2507c..5dd5b979 100644 --- a/tests/dbus/CMakeLists.txt +++ b/tests/dbus/CMakeLists.txt @@ -7,7 +7,8 @@ if(HAVE_TEST_PYTHON) endif(HAVE_TEST_PYTHON) if(ENABLE_TP_GLIB_TESTS) - include_directories(${TELEPATHY_GLIB_INCLUDE_DIR} + include_directories(${CMAKE_SOURCE_DIR}/tests/lib/glib + ${TELEPATHY_GLIB_INCLUDE_DIR} ${GLIB2_INCLUDE_DIR} ${DBUS_INCLUDE_DIR}) @@ -26,6 +27,7 @@ if(ENABLE_TP_GLIB_TESTS) tpqt_add_dbus_unit_test(ChannelConference chan-conference tp-glib-tests tp-qt-tests-glib-helpers) tpqt_add_dbus_unit_test(ChannelGroup chan-group tp-glib-tests tp-qt-tests-glib-helpers) tpqt_add_dbus_unit_test(ConnectionManagerBasics cm-basics tp-glib-tests) + tpqt_add_dbus_unit_test(ConnectionAddressing conn-addressing tp-glib-tests tp-qt-tests-glib-helpers) tpqt_add_dbus_unit_test(ConnectionBasics conn-basics tp-glib-tests) tpqt_add_dbus_unit_test(ConnectionCapabilities conn-capabilities tp-glib-tests tp-qt-tests-glib-helpers) tpqt_add_dbus_unit_test(ConnectionIntrospectCornercases conn-introspect-cornercases tp-glib-tests) diff --git a/tests/dbus/conn-addressing.cpp b/tests/dbus/conn-addressing.cpp new file mode 100644 index 00000000..887ff605 --- /dev/null +++ b/tests/dbus/conn-addressing.cpp @@ -0,0 +1,403 @@ +#include <tests/lib/test.h> + +#include <tests/lib/glib-helpers/test-conn-helper.h> + +#include <tests/lib/glib/future/conn-addressing/conn.h> + +#define TP_QT_ENABLE_LOWLEVEL_API + +#include <TelepathyQt/Connection> +#include <TelepathyQt/ConnectionLowlevel> +#include <TelepathyQt/Contact> +#include <TelepathyQt/ContactManager> +#include <TelepathyQt/PendingContacts> +#include <TelepathyQt/Types> + +#include <telepathy-glib/debug.h> + +using namespace Tp; + +class TestConnAddressing : public Test +{ + Q_OBJECT + +public: + TestConnAddressing(QObject *parent = 0) + : Test(parent) + { + } + +protected Q_SLOTS: + void expectPendingContactsFinished(Tp::PendingOperation *); + +private Q_SLOTS: + void initTestCase(); + void init(); + + void testSupport(); + void testRequest(); + void testRequestNoFeatures(); + void testRequestEmpty(); + + void cleanup(); + void cleanupTestCase(); + +private: + void commonTestRequest(bool withFeatures); + + TestConnHelper *mConn; + QList<ContactPtr> mContacts; + Tp::UIntList mInvalidHandles; + QStringList mValidIds; + QHash<QString, QPair<QString, QString> > mInvalidIds; + QStringList mValidVCardAddresses; + QStringList mInvalidVCardAddresses; + QStringList mValidUris; + QStringList mInvalidUris; +}; + +void TestConnAddressing::expectPendingContactsFinished(PendingOperation *op) +{ + TEST_VERIFY_OP(op); + + PendingContacts *pc = qobject_cast<PendingContacts *>(op); + mContacts = pc->contacts(); + mInvalidHandles = pc->invalidHandles(); + mValidIds = pc->validIdentifiers(); + mInvalidIds = pc->invalidIdentifiers(); + mValidVCardAddresses = pc->validVCardAddresses(); + mInvalidVCardAddresses = pc->invalidVCardAddresses(); + mValidUris = pc->validUris(); + mInvalidUris = pc->invalidUris(); + + mLoop->exit(0); +} + +void TestConnAddressing::initTestCase() +{ + initTestCaseImpl(); + + g_type_init(); + g_set_prgname("conn-addressing"); + tp_debug_set_flags("all"); + dbus_g_bus_get(DBUS_BUS_STARTER, 0); + + mConn = new TestConnHelper(this, + TP_TESTS_TYPE_ADDRESSING_CONNECTION, + "account", "me@example.com", + "protocol", "addressing", + NULL); + QVERIFY(mConn->connect()); +} + +void TestConnAddressing::init() +{ + initImpl(); + + mContacts.clear(); + mInvalidHandles.clear(); + mValidIds.clear(); + mInvalidIds.clear(); + mValidVCardAddresses.clear(); + mInvalidVCardAddresses.clear(); + mValidUris.clear(); + mInvalidUris.clear(); +} + +void TestConnAddressing::testSupport() +{ + ConnectionPtr conn = mConn->client(); + + QVERIFY(!conn->lowlevel()->contactAttributeInterfaces().isEmpty()); + + QVERIFY(conn->lowlevel()->contactAttributeInterfaces().contains( + TP_QT_IFACE_CONNECTION)); + QVERIFY(conn->lowlevel()->contactAttributeInterfaces().contains( + QLatin1String("org.freedesktop.Telepathy.Connection.Interface.Addressing.DRAFT"))); + + Features supportedFeatures = conn->contactManager()->supportedFeatures(); + QVERIFY(!supportedFeatures.isEmpty()); + QVERIFY(supportedFeatures.contains(Contact::FeatureAddresses)); +} + +void TestConnAddressing::commonTestRequest(bool withFeatures) +{ + ConnectionPtr conn = mConn->client(); + + Features features; + if (withFeatures) { + features << Contact::FeatureInfo << Contact::FeatureAddresses; + } + + QStringList validUris; + validUris << QLatin1String("addr:foo"); + QStringList invalidUris; + invalidUris << QLatin1String("invalid_uri:bar"); + QStringList uris(validUris); + uris.append(invalidUris); + PendingContacts *pc = conn->contactManager()->contactsForUris(uris, features); + + // Test the closure accessors + QCOMPARE(pc->manager(), conn->contactManager()); + QCOMPARE(pc->features(), features); + + QVERIFY(pc->isForUris()); + QCOMPARE(pc->uris(), uris); + QVERIFY(!pc->isForHandles()); + QVERIFY(pc->handles().isEmpty()); + QVERIFY(!pc->isForIdentifiers()); + QVERIFY(pc->identifiers().isEmpty()); + QVERIFY(!pc->isForVCardAddresses()); + QVERIFY(pc->vcardField().isEmpty()); + QVERIFY(pc->vcardAddresses().isEmpty()); + QVERIFY(!pc->isUpgrade()); + QVERIFY(pc->contactsToUpgrade().isEmpty()); + + // Wait for the contacts to be built + QVERIFY(connect(pc, + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(expectPendingContactsFinished(Tp::PendingOperation*)))); + QCOMPARE(mLoop->exec(), 0); + + // There should be 1 resulting contact ("foo") and 1 uri found to be invalid + QCOMPARE(mContacts.size(), 1); + QCOMPARE(mContacts[0]->id(), QLatin1String("foo")); + if (withFeatures) { + QVERIFY(!mContacts[0]->actualFeatures().contains(Contact::FeatureLocation)); + QVERIFY(mContacts[0]->actualFeatures().contains(Contact::FeatureInfo)); + QVERIFY(mContacts[0]->actualFeatures().contains(Contact::FeatureAddresses)); + QMap<QString, QString> vcardAddresses; + vcardAddresses.insert(QLatin1String("x-addr"), QLatin1String("foo")); + QStringList uris; + uris.append(QLatin1String("addr:foo")); + QCOMPARE(mContacts[0]->vcardAddresses(), vcardAddresses); + QCOMPARE(mContacts[0]->uris(), uris); + } else { + QVERIFY(!mContacts[0]->actualFeatures().contains(Contact::FeatureLocation)); + QVERIFY(!mContacts[0]->actualFeatures().contains(Contact::FeatureInfo)); + // FeatureAddresses will be enabled even if not requested when + // ContactManager::contactsForUris/VCardAddresses is used, + // but we don't want to guarantee that, implementation detail + } + QCOMPARE(mValidUris, validUris); + QCOMPARE(mInvalidUris, invalidUris); + QVERIFY(mInvalidHandles.isEmpty()); + QVERIFY(mValidIds.isEmpty()); + QVERIFY(mInvalidIds.isEmpty()); + QVERIFY(mValidVCardAddresses.isEmpty()); + QVERIFY(mInvalidVCardAddresses.isEmpty()); + + QStringList ids; + ids << QLatin1String("foo"); + QList<ContactPtr> contacts = mConn->contacts(ids); + QCOMPARE(contacts.size(), 1); + QCOMPARE(mContacts[0], contacts[0]); + + // let's test for vCard now + QString vcardField(QLatin1String("x-addr")); + QStringList vcardAddresses; + vcardAddresses << QLatin1String("foo") << QLatin1String("bar"); + vcardAddresses.sort(); + pc = conn->contactManager()->contactsForVCardAddresses(vcardField, + vcardAddresses, features); + + // Test the closure accessors + QCOMPARE(pc->manager(), conn->contactManager()); + QCOMPARE(pc->features(), features); + + QVERIFY(pc->isForVCardAddresses()); + QCOMPARE(pc->vcardField(), vcardField); + QCOMPARE(pc->vcardAddresses(), vcardAddresses); + QVERIFY(!pc->isForHandles()); + QVERIFY(pc->handles().isEmpty()); + QVERIFY(!pc->isForIdentifiers()); + QVERIFY(pc->identifiers().isEmpty()); + QVERIFY(!pc->isForUris()); + QVERIFY(pc->uris().isEmpty()); + QVERIFY(!pc->isUpgrade()); + QVERIFY(pc->contactsToUpgrade().isEmpty()); + + // Wait for the contacts to be built + QVERIFY(connect(pc, + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(expectPendingContactsFinished(Tp::PendingOperation*)))); + QCOMPARE(mLoop->exec(), 0); + + // There should be 1 resulting contact ("foo") and 1 uri found to be invalid + QCOMPARE(mContacts.size(), 2); + if (withFeatures) { + QVERIFY(!mContacts[0]->actualFeatures().contains(Contact::FeatureLocation)); + QVERIFY(mContacts[0]->actualFeatures().contains(Contact::FeatureInfo)); + QVERIFY(mContacts[0]->actualFeatures().contains(Contact::FeatureAddresses)); + QVERIFY(!mContacts[1]->actualFeatures().contains(Contact::FeatureLocation)); + QVERIFY(mContacts[1]->actualFeatures().contains(Contact::FeatureInfo)); + QVERIFY(mContacts[1]->actualFeatures().contains(Contact::FeatureAddresses)); + } else { + QVERIFY(!mContacts[0]->actualFeatures().contains(Contact::FeatureLocation)); + QVERIFY(!mContacts[0]->actualFeatures().contains(Contact::FeatureInfo)); + QVERIFY(!mContacts[1]->actualFeatures().contains(Contact::FeatureLocation)); + QVERIFY(!mContacts[1]->actualFeatures().contains(Contact::FeatureInfo)); + // FeatureAddresses will be enabled even if not requested when + // ContactManager::contactsForUris/VCardAddresses is used, + // but we don't want to guarantee that, implementation detail + } + mValidVCardAddresses.sort(); + QCOMPARE(mValidVCardAddresses, vcardAddresses); + QVERIFY(mInvalidVCardAddresses.isEmpty()); + QVERIFY(mInvalidHandles.isEmpty()); + QVERIFY(mValidIds.isEmpty()); + QVERIFY(mInvalidIds.isEmpty()); + QVERIFY(mValidUris.isEmpty()); + QVERIFY(mInvalidUris.isEmpty()); + + // contact "foo" should be one of the returned contacts + QVERIFY(mContacts[0] != mContacts[1]); + QVERIFY(mContacts.contains(contacts[0])); + contacts.clear(); + + ids.clear(); + ids << QLatin1String("foo") << QLatin1String("bar"); + contacts = mConn->contacts(ids); + QCOMPARE(contacts.size(), 2); + QVERIFY(contacts.contains(mContacts[0])); + QVERIFY(contacts.contains(mContacts[1])); +} + +void TestConnAddressing::testRequest() +{ + commonTestRequest(true); +} + +void TestConnAddressing::testRequestNoFeatures() +{ + commonTestRequest(false); +} + +void TestConnAddressing::testRequestEmpty() +{ + ConnectionPtr conn = mConn->client(); + + PendingContacts *pc = conn->contactManager()->contactsForHandles(UIntList()); + QVERIFY(connect(pc, + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(expectPendingContactsFinished(Tp::PendingOperation*)))); + QCOMPARE(mLoop->exec(), 0); + QVERIFY(pc->isForHandles()); + QVERIFY(pc->handles().isEmpty()); + QVERIFY(!pc->isForIdentifiers()); + QVERIFY(pc->identifiers().isEmpty()); + QVERIFY(!pc->isForUris()); + QVERIFY(pc->uris().isEmpty()); + QVERIFY(!pc->isForVCardAddresses()); + QVERIFY(pc->vcardField().isEmpty()); + QVERIFY(pc->vcardAddresses().isEmpty()); + QVERIFY(!pc->isUpgrade()); + QVERIFY(pc->contactsToUpgrade().isEmpty()); + QVERIFY(pc->contacts().isEmpty()); + QVERIFY(mInvalidHandles.isEmpty()); + QVERIFY(mValidIds.isEmpty()); + QVERIFY(mInvalidIds.isEmpty()); + QVERIFY(mValidUris.isEmpty()); + QVERIFY(mInvalidUris.isEmpty()); + QVERIFY(mValidVCardAddresses.isEmpty()); + QVERIFY(mInvalidVCardAddresses.isEmpty()); + + pc = conn->contactManager()->contactsForUris(QStringList()); + QVERIFY(connect(pc, + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(expectPendingContactsFinished(Tp::PendingOperation*)))); + QCOMPARE(mLoop->exec(), 0); + QVERIFY(pc->isForUris()); + QVERIFY(pc->uris().isEmpty()); + QVERIFY(!pc->isForHandles()); + QVERIFY(pc->handles().isEmpty()); + QVERIFY(!pc->isForIdentifiers()); + QVERIFY(pc->identifiers().isEmpty()); + QVERIFY(!pc->isForVCardAddresses()); + QVERIFY(pc->vcardField().isEmpty()); + QVERIFY(pc->vcardAddresses().isEmpty()); + QVERIFY(!pc->isUpgrade()); + QVERIFY(pc->contactsToUpgrade().isEmpty()); + QVERIFY(pc->contacts().isEmpty()); + QVERIFY(mValidUris.isEmpty()); + QVERIFY(mInvalidUris.isEmpty()); + QVERIFY(mInvalidHandles.isEmpty()); + QVERIFY(mValidIds.isEmpty()); + QVERIFY(mInvalidIds.isEmpty()); + QVERIFY(mValidVCardAddresses.isEmpty()); + QVERIFY(mInvalidVCardAddresses.isEmpty()); + + pc = conn->contactManager()->contactsForVCardAddresses(QString(), + QStringList()); + QVERIFY(connect(pc, + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(expectPendingContactsFinished(Tp::PendingOperation*)))); + QCOMPARE(mLoop->exec(), 0); + QVERIFY(pc->isForVCardAddresses()); + QVERIFY(pc->vcardField().isEmpty()); + QVERIFY(pc->vcardAddresses().isEmpty()); + QVERIFY(!pc->isForHandles()); + QVERIFY(pc->handles().isEmpty()); + QVERIFY(!pc->isForIdentifiers()); + QVERIFY(pc->identifiers().isEmpty()); + QVERIFY(!pc->isForUris()); + QVERIFY(pc->uris().isEmpty()); + QVERIFY(!pc->isUpgrade()); + QVERIFY(pc->contactsToUpgrade().isEmpty()); + QVERIFY(pc->contacts().isEmpty()); + QVERIFY(mValidVCardAddresses.isEmpty()); + QVERIFY(mInvalidVCardAddresses.isEmpty()); + QVERIFY(mInvalidHandles.isEmpty()); + QVERIFY(mValidIds.isEmpty()); + QVERIFY(mInvalidIds.isEmpty()); + QVERIFY(mValidUris.isEmpty()); + QVERIFY(mInvalidUris.isEmpty()); + + pc = conn->contactManager()->contactsForVCardAddresses(QLatin1String("x-unsupported"), + QStringList()); + QVERIFY(connect(pc, + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(expectPendingContactsFinished(Tp::PendingOperation*)))); + QCOMPARE(mLoop->exec(), 0); + QVERIFY(pc->isForVCardAddresses()); + QCOMPARE(pc->vcardField(), QLatin1String("x-unsupported")); + QVERIFY(pc->vcardAddresses().isEmpty()); + QVERIFY(!pc->isForHandles()); + QVERIFY(pc->handles().isEmpty()); + QVERIFY(!pc->isForIdentifiers()); + QVERIFY(pc->identifiers().isEmpty()); + QVERIFY(!pc->isForUris()); + QVERIFY(pc->uris().isEmpty()); + QVERIFY(!pc->isUpgrade()); + QVERIFY(pc->contactsToUpgrade().isEmpty()); + QVERIFY(pc->contacts().isEmpty()); + QVERIFY(mValidVCardAddresses.isEmpty()); + QVERIFY(mInvalidVCardAddresses.isEmpty()); + QVERIFY(mInvalidHandles.isEmpty()); + QVERIFY(mValidIds.isEmpty()); + QVERIFY(mInvalidIds.isEmpty()); + QVERIFY(mValidUris.isEmpty()); + QVERIFY(mInvalidUris.isEmpty()); +} + +void TestConnAddressing::cleanup() +{ + cleanupImpl(); +} + +void TestConnAddressing::cleanupTestCase() +{ + if (!mContacts.isEmpty()) { + mContacts.clear(); + } + + if (mConn) { + QVERIFY(mConn->disconnect()); + delete mConn; + } + + cleanupTestCaseImpl(); +} + +QTEST_MAIN(TestConnAddressing) +#include "_gen/conn-addressing.cpp.moc.hpp" diff --git a/tests/dbus/contacts.cpp b/tests/dbus/contacts.cpp index 2769871f..9b6eef6f 100644 --- a/tests/dbus/contacts.cpp +++ b/tests/dbus/contacts.cpp @@ -188,12 +188,15 @@ void TestContacts::testSupport() TP_QT_IFACE_CONNECTION_INTERFACE_AVATARS)); QVERIFY(mConn->lowlevel()->contactAttributeInterfaces().contains( TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE)); + QVERIFY(!mConn->lowlevel()->contactAttributeInterfaces().contains( + QLatin1String("org.freedesktop.Telepathy.Connection.Interface.Addressing.DRAFT"))); Features supportedFeatures = mConn->contactManager()->supportedFeatures(); QVERIFY(!supportedFeatures.isEmpty()); QVERIFY(supportedFeatures.contains(Contact::FeatureAlias)); QVERIFY(supportedFeatures.contains(Contact::FeatureAvatarToken)); QVERIFY(supportedFeatures.contains(Contact::FeatureSimplePresence)); + QVERIFY(!supportedFeatures.contains(Contact::FeatureAddresses)); } void TestContacts::testSelfContact() diff --git a/tests/lib/glib/CMakeLists.txt b/tests/lib/glib/CMakeLists.txt index 5979dabf..08af358c 100644 --- a/tests/lib/glib/CMakeLists.txt +++ b/tests/lib/glib/CMakeLists.txt @@ -64,6 +64,7 @@ if(ENABLE_TP_GLIB_TESTS) example-cm-echo example-cm-echo2 tp-glib-tests-future-extensions - future-example-cm-conference) + future-example-cm-conference + future-example-conn-addressing) endif(ENABLE_TP_GLIB_TESTS) diff --git a/tests/lib/glib/future/CMakeLists.txt b/tests/lib/glib/future/CMakeLists.txt index d995576d..46147974 100644 --- a/tests/lib/glib/future/CMakeLists.txt +++ b/tests/lib/glib/future/CMakeLists.txt @@ -1,4 +1,5 @@ if(ENABLE_TP_GLIB_TESTS) add_subdirectory(extensions) add_subdirectory(conference) + add_subdirectory(conn-addressing) endif(ENABLE_TP_GLIB_TESTS) diff --git a/tests/lib/glib/future/conn-addressing/CMakeLists.txt b/tests/lib/glib/future/conn-addressing/CMakeLists.txt new file mode 100644 index 00000000..6e4f6a71 --- /dev/null +++ b/tests/lib/glib/future/conn-addressing/CMakeLists.txt @@ -0,0 +1,14 @@ +if(ENABLE_TP_GLIB_TESTS) + include_directories( + ${CMAKE_SOURCE_DIR}/tests/lib/glib + ${CMAKE_SOURCE_DIR}/tests/lib/glib/future + ${DBUS_GLIB_INCLUDE_DIRS}) + + set(future_example_conn_addressing_SRCS + conn.c + conn.h) + + add_library(future-example-conn-addressing STATIC ${future_example_conn_addressing_SRCS}) + target_link_libraries(future-example-conn-addressing ${TPGLIB_LIBRARIES} + tp-glib-tests-future-extensions) +endif(ENABLE_TP_GLIB_TESTS) diff --git a/tests/lib/glib/future/conn-addressing/conn.c b/tests/lib/glib/future/conn-addressing/conn.c new file mode 100644 index 00000000..36a71084 --- /dev/null +++ b/tests/lib/glib/future/conn-addressing/conn.c @@ -0,0 +1,359 @@ +/* + * conn.c - connection implementing Conn.I.Addressing + * + * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2011 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 "conn.h" + +#include <dbus/dbus-glib-lowlevel.h> + +#include <telepathy-glib/connection.h> +#include <telepathy-glib/contacts-mixin.h> +#include <telepathy-glib/enums.h> +#include <telepathy-glib/gtypes.h> +#include <telepathy-glib/interfaces.h> + +#include "extensions/extensions.h" + +#include <string.h> + +static void addressing_fill_contact_attributes (GObject *obj, + const GArray *contacts, + GHashTable *attributes_hash); +static void addressing_iface_init (gpointer, gpointer); + +G_DEFINE_TYPE_WITH_CODE (TpTestsAddressingConnection, + tp_tests_addressing_connection, + TP_TESTS_TYPE_CONTACTS_CONNECTION, + G_IMPLEMENT_INTERFACE (FUTURE_TYPE_SVC_CONNECTION_INTERFACE_ADDRESSING, + addressing_iface_init); + ); + +struct _TpTestsAddressingConnectionPrivate +{ +}; + +static const gchar *addressable_vcard_fields[] = {"x-addr", NULL}; +static const gchar *addressable_uri_schemes[] = {"addr", NULL}; + +static const char *assumed_interfaces[] = { + TP_IFACE_CONNECTION, + FUTURE_IFACE_CONNECTION_INTERFACE_ADDRESSING, + NULL +}; + +static void +constructed (GObject *object) +{ + TpTestsAddressingConnection *self = TP_TESTS_ADDRESSING_CONNECTION (object); + void (*parent_impl) (GObject *) = + G_OBJECT_CLASS (tp_tests_addressing_connection_parent_class)->constructed; + + if (parent_impl != NULL) + parent_impl (object); + + tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (self), + FUTURE_IFACE_CONNECTION_INTERFACE_ADDRESSING, + addressing_fill_contact_attributes); +} + +static void +tp_tests_addressing_connection_init (TpTestsAddressingConnection *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + TP_TESTS_TYPE_ADDRESSING_CONNECTION, TpTestsAddressingConnectionPrivate); +} + +static void +finalize (GObject *object) +{ + G_OBJECT_CLASS (tp_tests_addressing_connection_parent_class)->finalize (object); +} + +static void +tp_tests_addressing_connection_class_init (TpTestsAddressingConnectionClass *klass) +{ + TpBaseConnectionClass *base_class = + (TpBaseConnectionClass *) klass; + GObjectClass *object_class = (GObjectClass *) 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_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_CONTACT_CAPABILITIES, + TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, + TP_IFACE_CONNECTION_INTERFACE_REQUESTS, + FUTURE_IFACE_CONNECTION_INTERFACE_ADDRESSING, + NULL }; + + object_class->constructed = constructed; + object_class->finalize = finalize; + g_type_class_add_private (klass, sizeof (TpTestsAddressingConnectionPrivate)); + + base_class->interfaces_always_present = interfaces_always_present; +} + +static gchar ** +uris_for_handle (TpHandleRepoIface *contact_repo, + TpHandle contact) +{ + GPtrArray *uris = g_ptr_array_new (); + const gchar * const *scheme; + + for (scheme = addressable_uri_schemes; *scheme != NULL; scheme++) + { + const gchar *identifier = tp_handle_inspect (contact_repo, contact); + gchar *uri = g_strdup_printf ("%s:%s", *scheme, identifier); + + if (uri != NULL) + { + g_ptr_array_add (uris, uri); + } + } + + g_ptr_array_add (uris, NULL); + return (gchar **) g_ptr_array_free (uris, FALSE); +} + +static GHashTable * +vcard_addresses_for_handle (TpHandleRepoIface *contact_repo, + TpHandle contact) +{ + GHashTable *addresses = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, (GDestroyNotify) g_free); + const gchar * const *field; + + for (field = addressable_vcard_fields; *field != NULL; field++) + { + const gchar *identifier = tp_handle_inspect (contact_repo, contact); + + if (identifier != NULL) + { + g_hash_table_insert (addresses, (gpointer) *field, g_strdup (identifier)); + } + } + + return addresses; +} + +static void +addressing_fill_contact_attributes (GObject *obj, + const GArray *contacts, + GHashTable *attributes_hash) +{ + guint i; + TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( + (TpBaseConnection *) obj, TP_HANDLE_TYPE_CONTACT); + + for (i = 0; i < contacts->len; i++) + { + TpHandle contact = g_array_index (contacts, TpHandle, i); + gchar **uris = uris_for_handle (contact_repo, contact); + GHashTable *addresses = vcard_addresses_for_handle (contact_repo, contact); + + tp_contacts_mixin_set_contact_attribute (attributes_hash, + contact, FUTURE_IFACE_CONNECTION_INTERFACE_ADDRESSING"/uris", + tp_g_value_slice_new_take_boxed (G_TYPE_STRV, uris)); + + tp_contacts_mixin_set_contact_attribute (attributes_hash, + contact, FUTURE_IFACE_CONNECTION_INTERFACE_ADDRESSING"/addresses", + tp_g_value_slice_new_take_boxed (TP_HASH_TYPE_STRING_STRING_MAP, addresses)); + } +} + +static gchar * +uri_to_id (const gchar *uri, + GError **error) +{ + gchar *scheme; + gchar *normalized_id = NULL; + + g_return_val_if_fail (uri != NULL, NULL); + + scheme = g_uri_parse_scheme (uri); + + if (scheme == NULL) + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "'%s' is not a valid URI", uri); + goto OUT; + } + else if (g_ascii_strcasecmp (scheme, "addr") == 0) + { + normalized_id = g_strdup (uri + strlen (scheme) + 1); /* Strip the scheme */ + } + else + { + g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, + "'%s' URI scheme is not supported by this protocol", + scheme); + goto OUT; + } + +OUT: + g_free (scheme); + + return normalized_id; +} + +static TpHandle +ensure_handle_from_uri (TpHandleRepoIface *repo, + const gchar *uri, + GError **error) +{ + TpHandle handle; + gchar *id = uri_to_id (uri, error); + + if (id == NULL) + return 0; + + handle = tp_handle_ensure (repo, id, NULL, error); + + g_free (id); + + return handle; +} + +static void +addressing_get_contacts_by_uri (FutureSvcConnectionInterfaceAddressing *iface, + const gchar **uris, + const gchar **interfaces, + DBusGMethodInvocation *context) +{ + const gchar **uri; + TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( + (TpBaseConnection *) iface, TP_HANDLE_TYPE_CONTACT); + GHashTable *attributes; + GHashTable *requested = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + GArray *handles = g_array_sized_new (TRUE, TRUE, sizeof (TpHandle), + g_strv_length ((gchar **) uris)); + gchar *sender = dbus_g_method_get_sender (context); + + for (uri = uris; *uri != NULL; uri++) + { + TpHandle h = ensure_handle_from_uri (contact_repo, *uri, NULL); + + if (h == 0) + continue; + + g_hash_table_insert (requested, g_strdup (*uri), GUINT_TO_POINTER (h)); + g_array_append_val (handles, h); + } + + attributes = tp_contacts_mixin_get_contact_attributes (G_OBJECT (iface), handles, + interfaces, assumed_interfaces, sender); + + future_svc_connection_interface_addressing_return_from_get_contacts_by_uri ( + context, requested, attributes); + + tp_handles_unref (contact_repo, handles); + g_hash_table_unref (requested); + g_hash_table_unref (attributes); + g_free (sender); +} + +static gchar * +vcard_address_to_id (const gchar *vcard_field, + const gchar *vcard_address, + GError **error) +{ + gchar *normalized_id = NULL; + + g_return_val_if_fail (vcard_field != NULL, NULL); + g_return_val_if_fail (vcard_address != NULL, NULL); + + if (g_ascii_strcasecmp (vcard_field, "x-addr") == 0) + { + normalized_id = g_strdup (vcard_address); + } + else + { + g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, + "'%s' vCard field is not supported by this protocol", vcard_field); + } + + return normalized_id; +} + +static TpHandle +ensure_handle_from_vcard_address (TpHandleRepoIface *repo, + const gchar *vcard_field, + const gchar *vcard_address, + GError **error) +{ + TpHandle handle; + gchar *normalized_id; + + normalized_id = vcard_address_to_id (vcard_field, vcard_address, error); + if (normalized_id == NULL) + return 0; + + handle = tp_handle_ensure (repo, normalized_id, NULL, error); + + g_free (normalized_id); + + return handle; +} + +static void +addressing_get_contacts_by_vcard_field (FutureSvcConnectionInterfaceAddressing *iface, + const gchar *field, + const gchar **addresses, + const gchar **interfaces, + DBusGMethodInvocation *context) +{ + const gchar **address; + TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( + (TpBaseConnection *) iface, TP_HANDLE_TYPE_CONTACT); + GHashTable *attributes; + GHashTable *requested = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + GArray *handles = g_array_sized_new (TRUE, TRUE, sizeof (TpHandle), + g_strv_length ((gchar **) addresses)); + gchar *sender = dbus_g_method_get_sender (context); + + for (address = addresses; *address != NULL; address++) + { + TpHandle h = ensure_handle_from_vcard_address (contact_repo, field, + *address, NULL); + + if (h == 0) + continue; + + g_hash_table_insert (requested, g_strdup (*address), GUINT_TO_POINTER (h)); + g_array_append_val (handles, h); + } + + attributes = tp_contacts_mixin_get_contact_attributes (G_OBJECT (iface), handles, + interfaces, assumed_interfaces, sender); + + future_svc_connection_interface_addressing_return_from_get_contacts_by_vcard_field ( + context, requested, attributes); + + tp_handles_unref (contact_repo, handles); + g_hash_table_unref (requested); + g_hash_table_unref (attributes); + g_free (sender); +} + +static void +addressing_iface_init (gpointer g_iface, gpointer iface_data) +{ +#define IMPLEMENT(x) \ + future_svc_connection_interface_addressing_implement_##x (\ + g_iface, addressing_##x) + + IMPLEMENT(get_contacts_by_uri); + IMPLEMENT(get_contacts_by_vcard_field); +#undef IMPLEMENT +} diff --git a/tests/lib/glib/future/conn-addressing/conn.h b/tests/lib/glib/future/conn-addressing/conn.h new file mode 100644 index 00000000..9e02ba9d --- /dev/null +++ b/tests/lib/glib/future/conn-addressing/conn.h @@ -0,0 +1,57 @@ +/* + * conn.h - header for a connection that implements Conn.I.Addressing + * + * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2011 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_ADDRESSING_CONN_H__ +#define __TP_TESTS_ADDRESSING_CONN_H__ + +#include <glib-object.h> +#include <telepathy-glib/base-connection.h> + +#include "contacts-conn.h" + +G_BEGIN_DECLS + +typedef struct _TpTestsAddressingConnection TpTestsAddressingConnection; +typedef struct _TpTestsAddressingConnectionClass TpTestsAddressingConnectionClass; +typedef struct _TpTestsAddressingConnectionPrivate TpTestsAddressingConnectionPrivate; + +struct _TpTestsAddressingConnectionClass { + TpTestsContactsConnectionClass parent_class; +}; + +struct _TpTestsAddressingConnection { + TpTestsContactsConnection parent; + + TpTestsAddressingConnectionPrivate *priv; +}; + +GType tp_tests_addressing_connection_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_ADDRESSING_CONNECTION \ + (tp_tests_addressing_connection_get_type ()) +#define TP_TESTS_ADDRESSING_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), TP_TESTS_TYPE_ADDRESSING_CONNECTION, \ + TpTestsAddressingConnection)) +#define TP_TESTS_ADDRESSING_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), TP_TESTS_TYPE_ADDRESSING_CONNECTION, \ + TpTestsAddressingConnectionClass)) +#define TP_TESTS_ADDRESSING_IS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TP_TESTS_TYPE_ADDRESSING_CONNECTION)) +#define TP_TESTS_ADDRESSING_IS_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TP_TESTS_TYPE_ADDRESSING_CONNECTION)) +#define TP_TESTS_ADDRESSING_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TESTS_TYPE_ADDRESSING_CONNECTION, \ + TpTestsAddressingConnectionClass)) + +G_END_DECLS + +#endif diff --git a/tests/lib/glib/future/extensions/CMakeLists.txt b/tests/lib/glib/future/extensions/CMakeLists.txt index a7f07534..b5eb4efe 100644 --- a/tests/lib/glib/future/extensions/CMakeLists.txt +++ b/tests/lib/glib/future/extensions/CMakeLists.txt @@ -13,6 +13,7 @@ if(ENABLE_TP_GLIB_TESTS) > ${CMAKE_CURRENT_BINARY_DIR}/_gen/all.xml DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/all.xml ${CMAKE_CURRENT_SOURCE_DIR}/channel.xml + ${CMAKE_CURRENT_SOURCE_DIR}/connection.xml ${CMAKE_CURRENT_SOURCE_DIR}/misc.xml ${CMAKE_SOURCE_DIR}/tools/xincludator.py) @@ -64,6 +65,7 @@ if(ENABLE_TP_GLIB_TESTS) ${CMAKE_SOURCE_DIR}/tools/glib-interfaces-gen.py) set(SPECS + connection channel misc) foreach(spec ${SPECS}) @@ -95,6 +97,7 @@ if(ENABLE_TP_GLIB_TESTS) endfunction(SVC_GENERATOR spec) svc_generator(channel) + svc_generator(connection) svc_generator(misc) set(NEW_FILES @@ -108,6 +111,8 @@ if(ENABLE_TP_GLIB_TESTS) ${CMAKE_CURRENT_BINARY_DIR}/_gen/signals-marshal.list ${CMAKE_CURRENT_BINARY_DIR}/_gen/svc-channel.c ${CMAKE_CURRENT_BINARY_DIR}/_gen/svc-channel.h + ${CMAKE_CURRENT_BINARY_DIR}/_gen/svc-connection.c + ${CMAKE_CURRENT_BINARY_DIR}/_gen/svc-connection.h ${CMAKE_CURRENT_BINARY_DIR}/_gen/svc-misc.c ${CMAKE_CURRENT_BINARY_DIR}/_gen/svc-misc.h) list(APPEND tp_glib_tests_future_extensions_SRCS ${NEW_FILES}) diff --git a/tests/lib/glib/future/extensions/all.xml b/tests/lib/glib/future/extensions/all.xml index 53cedc54..a10ccfda 100644 --- a/tests/lib/glib/future/extensions/all.xml +++ b/tests/lib/glib/future/extensions/all.xml @@ -5,6 +5,7 @@ <tp:title>Extensions from the future</tp:title> <xi:include href="channel.xml"/> +<xi:include href="connection.xml"/> <xi:include href="misc.xml"/> <xi:include href="../../../../../spec/generic-types.xml"/> diff --git a/tests/lib/glib/future/extensions/connection.xml b/tests/lib/glib/future/extensions/connection.xml new file mode 100644 index 00000000..209c94d3 --- /dev/null +++ b/tests/lib/glib/future/extensions/connection.xml @@ -0,0 +1,9 @@ +<tp:spec + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + xmlns:xi="http://www.w3.org/2001/XInclude"> + +<tp:title>Connections extensions from the future</tp:title> + +<xi:include href="../../../../../spec/Connection_Interface_Addressing.xml"/> + +</tp:spec> diff --git a/tests/lib/glib/future/extensions/extensions.h b/tests/lib/glib/future/extensions/extensions.h index 4f3bcfc1..3068e184 100644 --- a/tests/lib/glib/future/extensions/extensions.h +++ b/tests/lib/glib/future/extensions/extensions.h @@ -3,9 +3,11 @@ #include <glib-object.h> #include <telepathy-glib/channel.h> +#include <telepathy-glib/connection.h> #include "tests/lib/glib/future/extensions/_gen/enums.h" #include "tests/lib/glib/future/extensions/_gen/svc-channel.h" +#include "tests/lib/glib/future/extensions/_gen/svc-connection.h" #include "tests/lib/glib/future/extensions/_gen/svc-misc.h" G_BEGIN_DECLS |