summaryrefslogtreecommitdiff
path: root/qt4/tests/dbus/conn-roster-groups.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt4/tests/dbus/conn-roster-groups.cpp')
-rw-r--r--qt4/tests/dbus/conn-roster-groups.cpp856
1 files changed, 856 insertions, 0 deletions
diff --git a/qt4/tests/dbus/conn-roster-groups.cpp b/qt4/tests/dbus/conn-roster-groups.cpp
new file mode 100644
index 000000000..7d5a3e6d3
--- /dev/null
+++ b/qt4/tests/dbus/conn-roster-groups.cpp
@@ -0,0 +1,856 @@
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
+#include <QtDBus/QtDBus>
+
+#include <QtTest/QtTest>
+
+#define TP_QT4_ENABLE_LOWLEVEL_API
+
+#include <TelepathyQt4/ChannelFactory>
+#include <TelepathyQt4/Connection>
+#include <TelepathyQt4/ConnectionLowlevel>
+#include <TelepathyQt4/Contact>
+#include <TelepathyQt4/ContactFactory>
+#include <TelepathyQt4/ContactManager>
+#include <TelepathyQt4/PendingContacts>
+#include <TelepathyQt4/PendingReady>
+#include <TelepathyQt4/Debug>
+
+#include <telepathy-glib/debug.h>
+
+#include <tests/lib/glib/contactlist2/conn.h>
+#include <tests/lib/test.h>
+
+using namespace Tp;
+
+class TestConnRosterGroups : public Test
+{
+ Q_OBJECT
+
+public:
+ TestConnRosterGroups(QObject *parent = 0)
+ : Test(parent), mConnService(0),
+ mContactsAddedToGroup(0), mContactsRemovedFromGroup(0)
+ { }
+
+private:
+ void causeCongestion(const ConnectionPtr &conn, const ContactPtr &contact);
+
+protected Q_SLOTS:
+ void onGroupAdded(const QString &group);
+ void onGroupRemoved(const QString &group);
+ void onContactAddedToGroup(const QString &group);
+ void onContactRemovedFromGroup(const QString &group);
+ void expectConnInvalidated();
+ void expectContact(Tp::PendingOperation*);
+ void exitOnStateSuccess(Tp::ContactListState);
+
+private Q_SLOTS:
+ void initTestCase();
+ void init();
+
+ void testGroupsAfterStateChange();
+ void testIntrospectAfterStateChange();
+ void testRosterGroups();
+ void testNotADeathTrap();
+
+ void cleanup();
+ void cleanupTestCase();
+
+private:
+ QString mConnName, mConnPath;
+ ExampleContactListConnection *mConnService;
+ ConnectionPtr mConn;
+ ContactPtr mContact;
+
+ QString mGroupAdded;
+ QString mGroupRemoved;
+ int mContactsAddedToGroup;
+ int mContactsRemovedFromGroup;
+ bool mConnInvalidated;
+};
+
+void TestConnRosterGroups::causeCongestion(const ConnectionPtr &conn, const ContactPtr &contact)
+{
+ // Cause some congestion in the roster events queue so we can check that it doesn't cause
+ // inconsistent event reordering
+ for (int i = 0; i < 5; i++) {
+ QString name = QString(QLatin1String("Rush%1")).arg(i);
+ conn->contactManager()->addGroup(name);
+ conn->contactManager()->addContactsToGroup(name, QList<ContactPtr>() << contact);
+ contact->requestPresenceSubscription();
+ contact->removePresenceSubscription();
+ conn->contactManager()->removeGroup(name);
+ }
+}
+
+void TestConnRosterGroups::onGroupAdded(const QString &group)
+{
+ if (group.startsWith(QLatin1String("Rush"))) {
+ return;
+ }
+
+ mGroupAdded = group;
+}
+
+void TestConnRosterGroups::onGroupRemoved(const QString &group)
+{
+ if (group.startsWith(QLatin1String("Rush"))) {
+ return;
+ }
+
+ mGroupRemoved = group;
+}
+
+void TestConnRosterGroups::onContactAddedToGroup(const QString &group)
+{
+ if (group.startsWith(QLatin1String("Rush"))) {
+ return;
+ }
+
+ mContactsAddedToGroup++;
+}
+
+void TestConnRosterGroups::onContactRemovedFromGroup(const QString &group)
+{
+ if (group.startsWith(QLatin1String("Rush"))) {
+ return;
+ }
+
+ mContactsRemovedFromGroup++;
+}
+
+void TestConnRosterGroups::expectConnInvalidated()
+{
+ mConnInvalidated = true;
+ mLoop->exit(0);
+}
+
+void TestConnRosterGroups::expectContact(Tp::PendingOperation *op)
+{
+ PendingContacts *contacts = qobject_cast<PendingContacts *>(op);
+ QVERIFY(contacts != 0);
+
+ QVERIFY(contacts->isValid());
+ QCOMPARE(contacts->contacts().length(), 1);
+
+ mContact = contacts->contacts()[0];
+
+ mLoop->exit(0);
+}
+
+void TestConnRosterGroups::exitOnStateSuccess(Tp::ContactListState state)
+{
+ qDebug() << "got contact list state" << state;
+
+ if (state == ContactListStateSuccess) {
+ mLoop->exit(0);
+ }
+}
+
+void TestConnRosterGroups::initTestCase()
+{
+ initTestCaseImpl();
+
+ g_type_init();
+ g_set_prgname("conn-roster-groups");
+ tp_debug_set_flags("all");
+ dbus_g_bus_get(DBUS_BUS_STARTER, 0);
+}
+
+void TestConnRosterGroups::init()
+{
+ gchar *name;
+ gchar *connPath;
+ GError *error = 0;
+
+ mConnService = EXAMPLE_CONTACT_LIST_CONNECTION(g_object_new(
+ EXAMPLE_TYPE_CONTACT_LIST_CONNECTION,
+ "account", "me@example.com",
+ "simulation-delay", 0,
+ "protocol", "example-contact-list",
+ NULL));
+ QVERIFY(mConnService != 0);
+ QVERIFY(tp_base_connection_register(TP_BASE_CONNECTION(mConnService),
+ "foo", &name, &connPath, &error));
+ QVERIFY(error == 0);
+
+ QVERIFY(name != 0);
+ QVERIFY(connPath != 0);
+
+ mConnName = QLatin1String(name);
+ mConnPath = QLatin1String(connPath);
+
+ g_free(name);
+ g_free(connPath);
+ initImpl();
+
+ mConnInvalidated = false;
+}
+
+void TestConnRosterGroups::testGroupsAfterStateChange()
+{
+ // Create a conn and make the roster groups related features ready
+ mConn = Connection::create(mConnName, mConnPath,
+ ChannelFactory::create(QDBusConnection::sessionBus()),
+ ContactFactory::create());
+
+ ContactManagerPtr contactManager = mConn->contactManager();
+
+ Features features = Features() << Connection::FeatureRoster << Connection::FeatureRosterGroups;
+ QVERIFY(connect(mConn->becomeReady(features),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mConn->isReady(Connection::FeatureRoster), true);
+ QCOMPARE(mConn->isReady(Connection::FeatureRosterGroups), true);
+
+ // Now start connecting it, and wait for the ContactManager state to turn to Success
+ QVERIFY(connect(contactManager.data(),
+ SIGNAL(stateChanged(Tp::ContactListState)),
+ SLOT(exitOnStateSuccess(Tp::ContactListState))));
+
+ mConn->lowlevel()->requestConnect();
+
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(static_cast<uint>(contactManager->state()),
+ static_cast<uint>(ContactListStateSuccess));
+
+ // The conn should be valid and have the roster groups features ready when it emits Success
+ QVERIFY(mConn->isValid());
+ QCOMPARE(mConn->isReady(Connection::FeatureRoster), true);
+ QCOMPARE(mConn->isReady(Connection::FeatureRosterGroups), true);
+
+ // We should have all the group data downloaded now, check for that
+ QStringList expectedGroups;
+ expectedGroups << QLatin1String("Cambridge") << QLatin1String("Francophones")
+ << QLatin1String("Montreal");
+ expectedGroups.sort();
+ QStringList groups = contactManager->allKnownGroups();
+ groups.sort();
+ QCOMPARE(groups, expectedGroups);
+
+ // Cambridge
+ {
+ QStringList expectedContacts;
+ expectedContacts << QLatin1String("geraldine@example.com")
+ << QLatin1String("helen@example.com")
+ << QLatin1String("guillaume@example.com")
+ << QLatin1String("sjoerd@example.com");
+ expectedContacts.sort();
+ QStringList contacts;
+ Q_FOREACH (const ContactPtr &contact, contactManager->groupContacts(QLatin1String("Cambridge"))) {
+ contacts << contact->id();
+ }
+ contacts.sort();
+ QCOMPARE(contacts, expectedContacts);
+ }
+
+ // Francophones
+ {
+ QStringList expectedContacts;
+ expectedContacts << QLatin1String("olivier@example.com")
+ << QLatin1String("geraldine@example.com")
+ << QLatin1String("guillaume@example.com");
+ expectedContacts.sort();
+ QStringList contacts;
+ Q_FOREACH (const ContactPtr &contact, contactManager->groupContacts(QLatin1String("Francophones"))) {
+ contacts << contact->id();
+ }
+ contacts.sort();
+ QCOMPARE(contacts, expectedContacts);
+ }
+
+ // Montreal
+ {
+ QStringList expectedContacts;
+ expectedContacts << QLatin1String("olivier@example.com");
+ expectedContacts.sort();
+ QStringList contacts;
+ Q_FOREACH (const ContactPtr &contact, contactManager->groupContacts(QLatin1String("Montreal"))) {
+ contacts << contact->id();
+ }
+ contacts.sort();
+ QCOMPARE(contacts, expectedContacts);
+ }
+}
+
+void TestConnRosterGroups::testIntrospectAfterStateChange()
+{
+ // Create a conn and make the roster feature ready
+ mConn = Connection::create(mConnName, mConnPath,
+ ChannelFactory::create(QDBusConnection::sessionBus()),
+ ContactFactory::create());
+
+ ContactManagerPtr contactManager = mConn->contactManager();
+
+ Features features = Features() << Connection::FeatureRoster;
+ QVERIFY(connect(mConn->becomeReady(features),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mConn->isReady(Connection::FeatureRoster), true);
+ QCOMPARE(mConn->isReady(Connection::FeatureRosterGroups), false);
+
+ // Now start connecting it, and wait for the ContactManager state to turn to Success
+ QVERIFY(connect(contactManager.data(),
+ SIGNAL(stateChanged(Tp::ContactListState)),
+ SLOT(exitOnStateSuccess(Tp::ContactListState))));
+
+ mConn->lowlevel()->requestConnect();
+
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(static_cast<uint>(contactManager->state()),
+ static_cast<uint>(ContactListStateSuccess));
+
+ // The conn should be valid and have the roster feature ready when it emits Success, but not
+ // RosterGroups because we didn't request it
+ QVERIFY(mConn->isValid());
+ QCOMPARE(mConn->isReady(Connection::FeatureRoster), true);
+ QCOMPARE(mConn->isReady(Connection::FeatureRosterGroups), false);
+
+ // We should have roster contacts now, but no groups
+ QVERIFY(!contactManager->allKnownContacts().isEmpty());
+ QVERIFY(contactManager->allKnownGroups().isEmpty());
+
+ // Make RosterGroups ready too
+ features = Features() << Connection::FeatureRosterGroups;
+ QVERIFY(connect(mConn->becomeReady(features),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mConn->isReady(Connection::FeatureRoster), true);
+ QCOMPARE(mConn->isReady(Connection::FeatureRosterGroups), true);
+
+ // We should still have the contacts, and the state should be success
+ QVERIFY(!contactManager->allKnownContacts().isEmpty());
+ QCOMPARE(static_cast<uint>(contactManager->state()),
+ static_cast<uint>(ContactListStateSuccess));
+
+ // We should have all the group data downloaded now, check for that
+ QStringList expectedGroups;
+ expectedGroups << QLatin1String("Cambridge") << QLatin1String("Francophones")
+ << QLatin1String("Montreal");
+ expectedGroups.sort();
+ QStringList groups = contactManager->allKnownGroups();
+ groups.sort();
+ QCOMPARE(groups, expectedGroups);
+
+ // Cambridge
+ {
+ QStringList expectedContacts;
+ expectedContacts << QLatin1String("geraldine@example.com")
+ << QLatin1String("helen@example.com")
+ << QLatin1String("guillaume@example.com")
+ << QLatin1String("sjoerd@example.com");
+ expectedContacts.sort();
+ QStringList contacts;
+ Q_FOREACH (const ContactPtr &contact, contactManager->groupContacts(QLatin1String("Cambridge"))) {
+ contacts << contact->id();
+ }
+ contacts.sort();
+ QCOMPARE(contacts, expectedContacts);
+ }
+}
+
+void TestConnRosterGroups::testRosterGroups()
+{
+ mConn = Connection::create(mConnName, mConnPath,
+ ChannelFactory::create(QDBusConnection::sessionBus()),
+ ContactFactory::create());
+
+ QVERIFY(connect(mConn->lowlevel()->requestConnect(),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mConn->isReady(), true);
+ QCOMPARE(mConn->status(), ConnectionStatusConnected);
+
+ Features features = Features() << Connection::FeatureRoster << Connection::FeatureRosterGroups
+ << Connection::FeatureSelfContact;
+ QVERIFY(connect(mConn->becomeReady(features),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mConn->isReady(features), true);
+
+ QCOMPARE(static_cast<uint>(mConn->contactManager()->state()),
+ static_cast<uint>(ContactListStateSuccess));
+
+ ContactManagerPtr contactManager = mConn->contactManager();
+
+ QStringList expectedGroups;
+ expectedGroups << QLatin1String("Cambridge") << QLatin1String("Francophones")
+ << QLatin1String("Montreal");
+ expectedGroups.sort();
+ QStringList groups = contactManager->allKnownGroups();
+ groups.sort();
+ QCOMPARE(groups, expectedGroups);
+
+ QString group(QLatin1String("foo"));
+ QVERIFY(contactManager->groupContacts(group).isEmpty());
+
+ causeCongestion(mConn, mConn->selfContact());
+
+ // add group foo
+ QVERIFY(connect(contactManager.data(),
+ SIGNAL(groupAdded(const QString&)),
+ SLOT(onGroupAdded(const QString&))));
+
+ causeCongestion(mConn, mConn->selfContact());
+
+ QVERIFY(connect(contactManager->addGroup(group),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(!mGroupAdded.isEmpty());
+ QCOMPARE(mGroupAdded, group);
+
+ expectedGroups << group;
+ expectedGroups.sort();
+ groups = contactManager->allKnownGroups();
+ groups.sort();
+ QCOMPARE(groups, expectedGroups);
+
+ causeCongestion(mConn, mConn->selfContact());
+
+ // add Montreal contacts to group foo
+ Contacts contacts = contactManager->groupContacts(QLatin1String("Montreal"));
+ Q_FOREACH (const ContactPtr &contact, contacts) {
+ QVERIFY(connect(contact.data(),
+ SIGNAL(addedToGroup(const QString&)),
+ SLOT(onContactAddedToGroup(const QString&))));
+ }
+
+ causeCongestion(mConn, mConn->selfContact());
+
+ QVERIFY(connect(contactManager->addContactsToGroup(group, contacts.toList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mContactsAddedToGroup, contacts.size());
+ Q_FOREACH (const ContactPtr &contact, contacts) {
+ QVERIFY(contact->groups().contains(group));
+ }
+
+ causeCongestion(mConn, mConn->selfContact());
+
+ // remove all contacts from group foo
+ contacts = contactManager->groupContacts(group);
+ Q_FOREACH (const ContactPtr &contact, contacts) {
+ QVERIFY(connect(contact.data(),
+ SIGNAL(removedFromGroup(const QString&)),
+ SLOT(onContactRemovedFromGroup(const QString&))));
+ }
+
+ causeCongestion(mConn, mConn->selfContact());
+
+ QVERIFY(connect(contactManager->removeContactsFromGroup(group, contacts.toList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mContactsRemovedFromGroup, contacts.size());
+ Q_FOREACH (const ContactPtr &contact, contacts) {
+ QVERIFY(!contact->groups().contains(group));
+ }
+
+ causeCongestion(mConn, mConn->selfContact());
+
+ // remove group foo
+ QVERIFY(connect(contactManager.data(),
+ SIGNAL(groupRemoved(const QString&)),
+ SLOT(onGroupRemoved(const QString&))));
+
+ causeCongestion(mConn, mConn->selfContact());
+
+ QVERIFY(connect(contactManager->removeGroup(group),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(!mGroupRemoved.isEmpty());
+ QCOMPARE(mGroupRemoved, group);
+
+ expectedGroups.removeOne(group);
+ expectedGroups.sort();
+ groups = contactManager->allKnownGroups();
+ groups.sort();
+ QCOMPARE(groups, expectedGroups);
+}
+
+/**
+ * Verify that ContactManager isn't a death-trap.
+ *
+ * Background: Connection::contactManager() used to unpredictably waver between NULL and the real
+ * manager when the connection was in the process of being disconnected / otherwise invalidated,
+ * which led to a great many segfaults, which was especially unfortunate considering the
+ * ContactManager methods didn't do much any checks at all.
+ */
+void TestConnRosterGroups::testNotADeathTrap()
+{
+ mConn = Connection::create(mConnName, mConnPath,
+ ChannelFactory::create(QDBusConnection::sessionBus()),
+ ContactFactory::create());
+ QCOMPARE(mConn->isReady(), false);
+
+ // Check that the contact manager doesn't crash, but returns an error (because the conn isn't
+ // ready)
+ QVERIFY(!mConn->contactManager().isNull());
+ QVERIFY(connect(mConn->contactManager()->contactsForIdentifiers(QStringList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->lowlevel()->requestConnect(),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mConn->isReady(), true);
+ QCOMPARE(mConn->status(), ConnectionStatusConnected);
+
+ // As the conn is now ready, the contact building functions shouldn't return an error now
+ QVERIFY(!mConn->contactManager().isNull());
+
+ QVERIFY(connect(mConn->contactManager()->contactsForIdentifiers(QStringList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->contactsForHandles(UIntList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->upgradeContacts(QList<ContactPtr>(),
+ Features()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ // In fact, let's build a contact for future use
+ QVERIFY(connect(mConn->contactManager()->contactsForIdentifiers(
+ QStringList() << QLatin1String("friendorfoe@example.com")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectContact(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(mContact->id() == QLatin1String("friendorfoe@example.com"));
+
+ // Roster operations SHOULD still fail though, as FeatureRoster isn't ready
+ QVERIFY(connect(mConn->contactManager()->requestPresenceSubscription(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("I just want to see you fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->removePresenceSubscription(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("I just want to see you fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->authorizePresencePublication(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("I just want to see you fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->removePresencePublication(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("I just want to see you fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ // Now, make Roster ready
+ Features features = Features() << Connection::FeatureRoster;
+ QVERIFY(connect(mConn->becomeReady(features),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mConn->isReady(features), true);
+
+ causeCongestion(mConn, mContact);
+
+ // The roster functions should work now
+ QVERIFY(connect(mConn->contactManager()->requestPresenceSubscription(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("Please don't fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(mContact->subscriptionState() != Contact::PresenceStateNo);
+
+ causeCongestion(mConn, mContact);
+
+ QVERIFY(connect(mConn->contactManager()->removePresenceSubscription(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("Please don't fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QCOMPARE(mContact->subscriptionState(), Contact::PresenceStateNo);
+
+ causeCongestion(mConn, mContact);
+
+ QVERIFY(connect(mConn->contactManager()->authorizePresencePublication(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("Please don't fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ causeCongestion(mConn, mContact);
+
+ QVERIFY(connect(mConn->contactManager()->removePresencePublication(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("Please don't fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ // ... but still not the RosterGroup ones
+ QVERIFY(connect(mConn->contactManager()->addGroup(QLatin1String("Those who failed")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->removeGroup(QLatin1String("Those who failed")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->addContactsToGroup(QLatin1String("Those who failed"),
+ QList<ContactPtr>() << mContact),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->removeContactsFromGroup(QLatin1String("Those who failed"),
+ QList<ContactPtr>() << mContact),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ // Make RosterGroups ready too
+ features = Features() << Connection::FeatureRosterGroups;
+ QVERIFY(connect(mConn->becomeReady(features),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mConn->isReady(features), true);
+
+ // Now that Core, Roster and RosterGroups are all ready, everything should work
+ QVERIFY(!mConn->contactManager().isNull());
+
+ QVERIFY(connect(mConn->contactManager()->contactsForIdentifiers(QStringList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->contactsForHandles(UIntList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->upgradeContacts(QList<ContactPtr>(),
+ Features()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ causeCongestion(mConn, mContact);
+
+ QVERIFY(connect(mConn->contactManager()->requestPresenceSubscription(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("Please don't fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(mContact->subscriptionState() != Contact::PresenceStateNo);
+
+ causeCongestion(mConn, mContact);
+
+ QVERIFY(connect(mConn->contactManager()->removePresenceSubscription(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("Please don't fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QCOMPARE(mContact->subscriptionState(), Contact::PresenceStateNo);
+
+ QVERIFY(connect(mConn->contactManager()->authorizePresencePublication(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("Please don't fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->removePresencePublication(
+ QList<ContactPtr>() << mContact,
+ QLatin1String("Please don't fail")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ causeCongestion(mConn, mContact);
+
+ QVERIFY(connect(mConn->contactManager()->addGroup(QLatin1String("My successful entourage")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(mConn->contactManager()->allKnownGroups().contains(QLatin1String("My successful entourage")));
+
+ causeCongestion(mConn, mContact);
+
+ QVERIFY(connect(mConn->contactManager()->addContactsToGroup(QLatin1String("My successful entourage"),
+ QList<ContactPtr>() << mContact),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(mConn->contactManager()->
+ groupContacts(QLatin1String("My successful entourage")).contains(mContact));
+
+ causeCongestion(mConn, mContact);
+
+ QVERIFY(connect(mConn->contactManager()->removeContactsFromGroup(QLatin1String("My successful entourage"),
+ QList<ContactPtr>() << mContact),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(!mConn->contactManager()->
+ groupContacts(QLatin1String("My successful entourage")).contains(mContact));
+
+ causeCongestion(mConn, mContact);
+
+ QVERIFY(connect(mConn->contactManager()->removeGroup(QLatin1String("My successful entourage")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(!mConn->contactManager()->allKnownGroups().contains(QLatin1String("My successful entourage")));
+
+ // Now, invalidate the connection by disconnecting it
+ QVERIFY(connect(mConn.data(),
+ SIGNAL(invalidated(Tp::DBusProxy *,
+ const QString &, const QString &)),
+ SLOT(expectConnInvalidated())));
+ mConn->lowlevel()->requestDisconnect();
+
+ // Check that contactManager doesn't go NULL in the process of the connection going invalidated
+ do {
+ QVERIFY(!mConn->contactManager().isNull());
+ mLoop->processEvents();
+ } while (!mConnInvalidated);
+
+ QVERIFY(!mConn->isValid());
+ QCOMPARE(mConn->status(), ConnectionStatusDisconnected);
+
+ // Now that the conn is invalidated NOTHING should work anymore
+ QVERIFY(connect(mConn->contactManager()->contactsForIdentifiers(QStringList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->contactsForHandles(UIntList()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->upgradeContacts(QList<ContactPtr>(),
+ Features()),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->requestPresenceSubscription(QList<ContactPtr>(),
+ QLatin1String("You fail at life")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->removePresenceSubscription(QList<ContactPtr>(),
+ QLatin1String("You fail at life")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->authorizePresencePublication(QList<ContactPtr>(),
+ QLatin1String("You fail at life")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->removePresencePublication(QList<ContactPtr>(),
+ QLatin1String("You fail at life")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->addGroup(QLatin1String("Future failures")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->removeGroup(QLatin1String("Future failures")),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->addContactsToGroup(QLatin1String("Future failures"),
+ QList<ContactPtr>() << mContact),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ QVERIFY(connect(mConn->contactManager()->removeContactsFromGroup(QLatin1String("Future failures"),
+ QList<ContactPtr>() << mContact),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectFailure(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+}
+
+void TestConnRosterGroups::cleanup()
+{
+ mContact.reset();
+
+ if (mConn && mConn->requestedFeatures().contains(Connection::FeatureCore)) {
+ QVERIFY(mConnService != NULL);
+
+ if (TP_BASE_CONNECTION(mConnService)->status != TP_CONNECTION_STATUS_DISCONNECTED) {
+ tp_base_connection_change_status(TP_BASE_CONNECTION(mConnService),
+ TP_CONNECTION_STATUS_DISCONNECTED,
+ TP_CONNECTION_STATUS_REASON_REQUESTED);
+ }
+
+ while (mConn->isValid()) {
+ mLoop->processEvents();
+ }
+
+ }
+ mConn.reset();
+
+ if (mConnService != 0) {
+ g_object_unref(mConnService);
+ mConnService = 0;
+ }
+
+ cleanupImpl();
+}
+
+void TestConnRosterGroups::cleanupTestCase()
+{
+ cleanupTestCaseImpl();
+}
+
+QTEST_MAIN(TestConnRosterGroups)
+#include "_gen/conn-roster-groups.cpp.moc.hpp"