summaryrefslogtreecommitdiff
path: root/tests/dbus/conn-roster-legacy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/dbus/conn-roster-legacy.cpp')
-rw-r--r--tests/dbus/conn-roster-legacy.cpp376
1 files changed, 376 insertions, 0 deletions
diff --git a/tests/dbus/conn-roster-legacy.cpp b/tests/dbus/conn-roster-legacy.cpp
new file mode 100644
index 00000000..3422d140
--- /dev/null
+++ b/tests/dbus/conn-roster-legacy.cpp
@@ -0,0 +1,376 @@
+#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/PendingChannel>
+#include <TelepathyQt4/PendingContacts>
+#include <TelepathyQt4/PendingReady>
+#include <TelepathyQt4/Debug>
+
+#include <telepathy-glib/debug.h>
+
+#include <tests/lib/glib/contactlist/conn.h>
+#include <tests/lib/test.h>
+
+using namespace Tp;
+
+class TestConnRosterLegacy : public Test
+{
+ Q_OBJECT
+
+public:
+ TestConnRosterLegacy(QObject *parent = 0)
+ : Test(parent), mConnService(0)
+ { }
+
+protected Q_SLOTS:
+ void expectConnInvalidated();
+ void expectPendingContactsFinished(Tp::PendingOperation *);
+ void expectPresenceStateChanged(Tp::Contact::PresenceState);
+ void expectAllKnownContactsChanged(const Tp::Contacts &added, const Tp::Contacts &removed,
+ const Tp::Channel::GroupMemberChangeDetails &details);
+
+private Q_SLOTS:
+ void initTestCase();
+ void init();
+
+ void testRoster();
+
+ void cleanup();
+ void cleanupTestCase();
+
+private:
+ QString mConnName, mConnPath;
+ ExampleContactListConnection *mConnService;
+ ConnectionPtr mConn;
+ QList<ContactPtr> mContacts;
+ int mHowManyKnownContacts;
+ bool mGotPresenceStateChanged;
+};
+
+void TestConnRosterLegacy::expectConnInvalidated()
+{
+ mLoop->exit(0);
+}
+
+void TestConnRosterLegacy::expectPendingContactsFinished(PendingOperation *op)
+{
+ if (!op->isFinished()) {
+ qWarning() << "unfinished";
+ mLoop->exit(1);
+ return;
+ }
+
+ if (op->isError()) {
+ qWarning().nospace() << op->errorName()
+ << ": " << op->errorMessage();
+ mLoop->exit(2);
+ return;
+ }
+
+ if (!op->isValid()) {
+ qWarning() << "inconsistent results";
+ mLoop->exit(3);
+ return;
+ }
+
+ qDebug() << "finished";
+ PendingContacts *pending = qobject_cast<PendingContacts *>(op);
+ mContacts = pending->contacts();
+
+ mLoop->exit(0);
+}
+
+void TestConnRosterLegacy::expectAllKnownContactsChanged(const Tp::Contacts& added, const Tp::Contacts& removed,
+ const Tp::Channel::GroupMemberChangeDetails &details)
+{
+ qDebug() << added.size() << " contacts added, " << removed.size() << " contacts removed";
+ mHowManyKnownContacts += added.size();
+ mHowManyKnownContacts -= removed.size();
+
+ if (details.hasMessage()) {
+ QCOMPARE(details.message(), QLatin1String("add me now"));
+ }
+
+ if (mConn->contactManager()->allKnownContacts().size() != mHowManyKnownContacts) {
+ qWarning() << "Contacts number mismatch! Watched value: " << mHowManyKnownContacts
+ << "allKnownContacts(): " << mConn->contactManager()->allKnownContacts().size();
+ mLoop->exit(1);
+ } else {
+ mLoop->exit(0);
+ }
+}
+
+void TestConnRosterLegacy::expectPresenceStateChanged(Contact::PresenceState state)
+{
+ mGotPresenceStateChanged = true;
+}
+
+void TestConnRosterLegacy::initTestCase()
+{
+ initTestCaseImpl();
+
+ g_type_init();
+ g_set_prgname("conn-roster");
+ tp_debug_set_flags("all");
+ dbus_g_bus_get(DBUS_BUS_STARTER, 0);
+
+ gchar *name;
+ gchar *connPath;
+ GError *error = 0;
+
+ mConnService = EXAMPLE_CONTACT_LIST_CONNECTION(g_object_new(
+ EXAMPLE_TYPE_CONTACT_LIST_CONNECTION,
+ "account", "me@example.com",
+ "protocol", "contactlist",
+ "simulation-delay", 1,
+ NULL));
+ QVERIFY(mConnService != 0);
+ QVERIFY(tp_base_connection_register(TP_BASE_CONNECTION(mConnService),
+ "contacts", &name, &connPath, &error));
+ QVERIFY(error == 0);
+
+ QVERIFY(name != 0);
+ QVERIFY(connPath != 0);
+
+ mConnName = QLatin1String(name);
+ mConnPath = QLatin1String(connPath);
+
+ g_free(name);
+ g_free(connPath);
+}
+
+void TestConnRosterLegacy::init()
+{
+ initImpl();
+
+ 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);
+}
+
+void TestConnRosterLegacy::testRoster()
+{
+ Features features = Features() << Connection::FeatureRoster;
+ QVERIFY(connect(mConn->becomeReady(features),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ this,
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mConn->isReady(features), true);
+
+ QStringList toCheck = QStringList() <<
+ QLatin1String("sjoerd@example.com") <<
+ QLatin1String("travis@example.com") <<
+ QLatin1String("wim@example.com") <<
+ QLatin1String("olivier@example.com") <<
+ QLatin1String("helen@example.com") <<
+ QLatin1String("geraldine@example.com") <<
+ QLatin1String("guillaume@example.com") <<
+ QLatin1String("christian@example.com");
+ QStringList ids;
+ QList<ContactPtr> pendingSubscription;
+ QList<ContactPtr> pendingPublish;
+ Q_FOREACH (const ContactPtr &contact,
+ mConn->contactManager()->allKnownContacts()) {
+ qDebug() << " contact:" << contact->id() <<
+ "- subscription:" << contact->subscriptionState() <<
+ "- publish:" << contact->publishState();
+ ids << contact->id();
+ if (contact->subscriptionState() == Contact::PresenceStateAsk) {
+ pendingSubscription.append(contact);
+ } else if (contact->publishState() == Contact::PresenceStateAsk) {
+ pendingPublish.append(contact);
+ }
+ }
+ ids.sort();
+ toCheck.sort();
+ QCOMPARE(ids, toCheck);
+ QCOMPARE(pendingSubscription.size(), 2);
+ QCOMPARE(pendingPublish.size(), 2);
+
+ // Wait for the contacts to be built
+ ids = QStringList() << QString(QLatin1String("john@example.com"))
+ << QString(QLatin1String("mary@example.com"));
+ QVERIFY(connect(mConn->contactManager()->contactsForIdentifiers(ids),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectPendingContactsFinished(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ int i = 0;
+
+ Q_FOREACH (const ContactPtr &contact, mContacts) {
+ mGotPresenceStateChanged = false;
+
+ QVERIFY(connect(contact.data(),
+ SIGNAL(subscriptionStateChanged(Tp::Contact::PresenceState,Tp::Channel::GroupMemberChangeDetails)),
+ SLOT(expectPresenceStateChanged(Tp::Contact::PresenceState))));
+ QVERIFY(connect(contact.data(),
+ SIGNAL(publishStateChanged(Tp::Contact::PresenceState,Tp::Channel::GroupMemberChangeDetails)),
+ SLOT(expectPresenceStateChanged(Tp::Contact::PresenceState))));
+ if ((i % 2) == 0) {
+ contact->requestPresenceSubscription(QLatin1String("please add me"));
+ } else {
+ contact->requestPresenceSubscription(QLatin1String("add me now"));
+ }
+
+ while (!mGotPresenceStateChanged) {
+ mLoop->processEvents();
+ }
+
+ if ((i % 2) == 0) {
+ // I asked to see his presence - he might have already accepted it, though
+ QVERIFY(contact->subscriptionState() == Contact::PresenceStateAsk
+ || contact->subscriptionState() == Contact::PresenceStateYes);
+
+ // if he accepted it already, one iteration won't be enough as the
+ // first iteration will just flush the subscription -> Yes event
+ while (contact->publishState() != Contact::PresenceStateAsk) {
+ mLoop->processEvents();
+ }
+
+ contact->authorizePresencePublication();
+ while (contact->publishState() != Contact::PresenceStateYes) {
+ mLoop->processEvents();
+ }
+ // I authorized him to see my presence
+ QCOMPARE(static_cast<uint>(contact->publishState()),
+ static_cast<uint>(Contact::PresenceStateYes));
+ // He replied the presence request
+ QCOMPARE(static_cast<uint>(contact->subscriptionState()),
+ static_cast<uint>(Contact::PresenceStateYes));
+
+ contact->removePresenceSubscription();
+
+ while (contact->subscriptionState() != Contact::PresenceStateNo) {
+ mLoop->processEvents();
+ }
+ } else {
+ // I asked to see her presence - she might have already rejected it, though
+ QVERIFY(contact->subscriptionState() == Contact::PresenceStateAsk
+ || contact->subscriptionState() == Contact::PresenceStateNo);
+
+ // If she didn't already reject it, wait until she does
+ while (contact->subscriptionState() != Contact::PresenceStateNo) {
+ mLoop->processEvents();
+ }
+ }
+
+ ++i;
+
+ // Disconnect the signals so the contacts doing something won't early-exit future mainloop
+ // iterations (the simulation CM does things like - after a delay since we removed them, try
+ // to re-add us - and such, which mess up the test if the simulated network event happens
+ // before we've finished with the next contact)
+ QVERIFY(contact->disconnect(this));
+
+ // TODO: The roster API, frankly speaking, seems rather error/race prone, as evidenced by
+ // this test. Should we perhaps change its semantics? Then again, this test also simulates
+ // the remote user accepting/rejecting the request with a quite unpredictable timer delay,
+ // while real-world applications don't do any such assumptions about the timing of the
+ // remote user actions, so most of the problems won't be applicable there.
+ }
+
+ i = 0;
+ Contact::PresenceState expectedPresenceState;
+ Q_FOREACH (const ContactPtr &contact, pendingPublish) {
+ mGotPresenceStateChanged = false;
+
+ QVERIFY(connect(contact.data(),
+ SIGNAL(publishStateChanged(Tp::Contact::PresenceState,Tp::Channel::GroupMemberChangeDetails)),
+ SLOT(expectPresenceStateChanged(Tp::Contact::PresenceState))));
+
+ if ((i++ % 2) == 0) {
+ expectedPresenceState = Contact::PresenceStateYes;
+ contact->authorizePresencePublication();
+ } else {
+ expectedPresenceState = Contact::PresenceStateNo;
+ contact->removePresencePublication();
+ }
+
+ while (!mGotPresenceStateChanged) {
+ mLoop->processEvents();
+ }
+
+ QCOMPARE(static_cast<uint>(contact->publishState()),
+ static_cast<uint>(expectedPresenceState));
+ }
+
+ // Test allKnownContactsChanged.
+ // In this test, everytime a subscription is requested or rejected, allKnownContacts changes
+ // Cache the current value
+ mHowManyKnownContacts = mConn->contactManager()->allKnownContacts().size();
+ // Watch for contacts changed
+ QVERIFY(connect(mConn->contactManager().data(),
+ SIGNAL(allKnownContactsChanged(Tp::Contacts,Tp::Contacts,
+ Tp::Channel::GroupMemberChangeDetails)),
+ SLOT(expectAllKnownContactsChanged(Tp::Contacts,Tp::Contacts,
+ Tp::Channel::GroupMemberChangeDetails))));
+
+ // Wait for the contacts to be built
+ ids = QStringList() << QString(QLatin1String("kctest1@example.com"))
+ << QString(QLatin1String("kctest2@example.com"));
+ QVERIFY(connect(mConn->contactManager()->contactsForIdentifiers(ids),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectPendingContactsFinished(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ Q_FOREACH (const ContactPtr &contact, mContacts) {
+ contact->requestPresenceSubscription(QLatin1String("add me now"));
+
+ // allKnownContacts is supposed to change here.
+ QCOMPARE(mLoop->exec(), 0);
+ }
+}
+
+void TestConnRosterLegacy::cleanup()
+{
+ if (mConn) {
+ // Disconnect and wait for the readiness change
+ QVERIFY(connect(mConn->lowlevel()->requestDisconnect(),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ if (mConn->isValid()) {
+ QVERIFY(connect(mConn.data(),
+ SIGNAL(invalidated(Tp::DBusProxy *,
+ const QString &, const QString &)),
+ SLOT(expectConnInvalidated())));
+ QCOMPARE(mLoop->exec(), 0);
+ }
+ }
+
+ cleanupImpl();
+}
+
+void TestConnRosterLegacy::cleanupTestCase()
+{
+ if (mConnService != 0) {
+ g_object_unref(mConnService);
+ mConnService = 0;
+ }
+
+ cleanupTestCaseImpl();
+}
+
+QTEST_MAIN(TestConnRosterLegacy)
+#include "_gen/conn-roster-legacy.cpp.moc.hpp"