summaryrefslogtreecommitdiff
path: root/qt4/tests/dbus/client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt4/tests/dbus/client.cpp')
-rw-r--r--qt4/tests/dbus/client.cpp858
1 files changed, 858 insertions, 0 deletions
diff --git a/qt4/tests/dbus/client.cpp b/qt4/tests/dbus/client.cpp
new file mode 100644
index 000000000..91aea854f
--- /dev/null
+++ b/qt4/tests/dbus/client.cpp
@@ -0,0 +1,858 @@
+#include <tests/lib/test.h>
+
+#include <tests/lib/glib-helpers/test-conn-helper.h>
+
+#include <tests/lib/glib/contacts-conn.h>
+#include <tests/lib/glib/echo/chan.h>
+
+#define TP_QT4_ENABLE_LOWLEVEL_API
+
+#include <TelepathyQt4/Account>
+#include <TelepathyQt4/AccountManager>
+#include <TelepathyQt4/AbstractClientHandler>
+#include <TelepathyQt4/AbstractClientObserver>
+#include <TelepathyQt4/Channel>
+#include <TelepathyQt4/ChannelClassSpec>
+#include <TelepathyQt4/ChannelDispatchOperation>
+#include <TelepathyQt4/ChannelRequest>
+#include <TelepathyQt4/ClientHandlerInterface>
+#include <TelepathyQt4/ClientInterfaceRequestsInterface>
+#include <TelepathyQt4/ClientObserverInterface>
+#include <TelepathyQt4/ClientRegistrar>
+#include <TelepathyQt4/Connection>
+#include <TelepathyQt4/ConnectionLowlevel>
+#include <TelepathyQt4/MethodInvocationContext>
+#include <TelepathyQt4/PendingAccount>
+#include <TelepathyQt4/PendingReady>
+
+#include <telepathy-glib/debug.h>
+
+using namespace Tp;
+using namespace Tp::Client;
+
+class ChannelRequestAdaptor : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Telepathy.ChannelRequest")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"org.freedesktop.Telepathy.ChannelRequest\" >\n"
+" <property name=\"Account\" type=\"o\" access=\"read\" />\n"
+" <property name=\"UserActionTime\" type=\"x\" access=\"read\" />\n"
+" <property name=\"PreferredHandler\" type=\"s\" access=\"read\" />\n"
+" <property name=\"Requests\" type=\"aa{sv}\" access=\"read\" />\n"
+" <property name=\"Interfaces\" type=\"as\" access=\"read\" />\n"
+" <method name=\"Proceed\" />\n"
+" <method name=\"Cancel\" />\n"
+" <signal name=\"Failed\" >\n"
+" <arg name=\"Error\" type=\"s\" />\n"
+" <arg name=\"Message\" type=\"s\" />\n"
+" </signal>\n"
+" <signal name=\"Succeeded\" />"
+" </interface>\n"
+ "")
+
+ Q_PROPERTY(QDBusObjectPath Account READ Account)
+ Q_PROPERTY(qulonglong UserActionTime READ UserActionTime)
+ Q_PROPERTY(QString PreferredHandler READ PreferredHandler)
+ Q_PROPERTY(Tp::QualifiedPropertyValueMapList Requests READ Requests)
+ Q_PROPERTY(QStringList Interfaces READ Interfaces)
+
+public:
+ ChannelRequestAdaptor(QDBusObjectPath account,
+ qulonglong userActionTime,
+ QString preferredHandler,
+ QualifiedPropertyValueMapList requests,
+ QStringList interfaces,
+ QObject *parent)
+ : QDBusAbstractAdaptor(parent),
+ mAccount(account), mUserActionTime(userActionTime),
+ mPreferredHandler(preferredHandler), mRequests(requests),
+ mInterfaces(interfaces)
+ {
+ }
+
+ virtual ~ChannelRequestAdaptor()
+ {
+ }
+
+public: // Properties
+ inline QDBusObjectPath Account() const
+ {
+ return mAccount;
+ }
+
+ inline qulonglong UserActionTime() const
+ {
+ return mUserActionTime;
+ }
+
+ inline QString PreferredHandler() const
+ {
+ return mPreferredHandler;
+ }
+
+ inline QualifiedPropertyValueMapList Requests() const
+ {
+ return mRequests;
+ }
+
+ inline QStringList Interfaces() const
+ {
+ return mInterfaces;
+ }
+
+public Q_SLOTS: // Methods
+ void Proceed()
+ {
+ }
+
+ void Cancel()
+ {
+ }
+
+Q_SIGNALS: // Signals
+ void Failed(const QString &error, const QString &message);
+ void Succeeded();
+
+private:
+ QDBusObjectPath mAccount;
+ qulonglong mUserActionTime;
+ QString mPreferredHandler;
+ QualifiedPropertyValueMapList mRequests;
+ QStringList mInterfaces;
+};
+
+// Totally incomplete mini version of ChannelDispatchOperation
+class ChannelDispatchOperationAdaptor : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Telepathy.ChannelDispatchOperation")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"org.freedesktop.Telepathy.ChannelDispatchOperation\" >\n"
+" <property name=\"Account\" type=\"o\" access=\"read\" />\n"
+" <property name=\"Connection\" type=\"o\" access=\"read\" />\n"
+" <property name=\"Channels\" type=\"a(oa{sv})\" access=\"read\" />\n"
+" <property name=\"Interfaces\" type=\"as\" access=\"read\" />\n"
+" <property name=\"PossibleHandlers\" type=\"as\" access=\"read\" />\n"
+" </interface>\n"
+ "")
+
+ Q_PROPERTY(QDBusObjectPath Account READ Account)
+ Q_PROPERTY(QDBusObjectPath Connection READ Connection)
+ Q_PROPERTY(Tp::ChannelDetailsList Channels READ Channels)
+ Q_PROPERTY(QStringList Interfaces READ Interfaces)
+ Q_PROPERTY(QStringList PossibleHandlers READ PossibleHandlers)
+
+public:
+ ChannelDispatchOperationAdaptor(const QDBusObjectPath &acc, const QDBusObjectPath &conn,
+ const ChannelDetailsList &channels, const QStringList &possibleHandlers,
+ QObject *parent)
+ : QDBusAbstractAdaptor(parent), mAccount(acc), mConn(conn), mChannels(channels),
+ mPossibleHandlers(possibleHandlers)
+ {
+ }
+
+ virtual ~ChannelDispatchOperationAdaptor()
+ {
+ }
+
+public: // Properties
+ inline QDBusObjectPath Account() const
+ {
+ return mAccount;
+ }
+
+ inline QDBusObjectPath Connection() const
+ {
+ return mConn;
+ }
+
+ inline ChannelDetailsList Channels() const
+ {
+ return mChannels;
+ }
+
+ inline QStringList Interfaces() const
+ {
+ return mInterfaces;
+ }
+
+ inline QStringList PossibleHandlers() const
+ {
+ return mPossibleHandlers;
+ }
+
+public Q_SLOTS:
+ inline void Claim()
+ {
+ // do nothing = no fail
+ }
+
+private:
+ QDBusObjectPath mAccount, mConn;
+ ChannelDetailsList mChannels;
+ QStringList mInterfaces;
+ QStringList mPossibleHandlers;
+};
+
+class MyClient : public QObject,
+ public AbstractClientObserver,
+ public AbstractClientApprover,
+ public AbstractClientHandler
+{
+ Q_OBJECT
+
+public:
+ static AbstractClientPtr create(const ChannelClassSpecList &channelFilter,
+ const AbstractClientHandler::Capabilities &capabilities,
+ bool bypassApproval = false,
+ bool wantsRequestNotification = false)
+ {
+ return AbstractClientPtr::dynamicCast(SharedPtr<MyClient>(
+ new MyClient(channelFilter, capabilities,
+ bypassApproval, wantsRequestNotification)));
+ }
+
+ MyClient(const ChannelClassSpecList &channelFilter,
+ const AbstractClientHandler::Capabilities &capabilities,
+ bool bypassApproval = false,
+ bool wantsRequestNotification = false)
+ : AbstractClientObserver(channelFilter),
+ AbstractClientApprover(channelFilter),
+ AbstractClientHandler(channelFilter, capabilities, wantsRequestNotification),
+ mBypassApproval(bypassApproval)
+ {
+ }
+
+ ~MyClient()
+ {
+ }
+
+ void observeChannels(const MethodInvocationContextPtr<> &context,
+ const AccountPtr &account,
+ const ConnectionPtr &connection,
+ const QList<ChannelPtr> &channels,
+ const ChannelDispatchOperationPtr &dispatchOperation,
+ const QList<ChannelRequestPtr> &requestsSatisfied,
+ const AbstractClientObserver::ObserverInfo &observerInfo)
+ {
+ mObserveChannelsAccount = account;
+ mObserveChannelsConnection = connection;
+ mObserveChannelsChannels = channels;
+ mObserveChannelsDispatchOperation = dispatchOperation;
+ mObserveChannelsRequestsSatisfied = requestsSatisfied;
+ mObserveChannelsObserverInfo = observerInfo;
+
+ context->setFinished();
+ QTimer::singleShot(0, this, SIGNAL(observeChannelsFinished()));
+ }
+
+ void addDispatchOperation(const MethodInvocationContextPtr<> &context,
+ const ChannelDispatchOperationPtr &dispatchOperation)
+ {
+ mAddDispatchOperationChannels = dispatchOperation->channels();
+ mAddDispatchOperationDispatchOperation = dispatchOperation;
+
+ QVERIFY(connect(dispatchOperation->claim(AbstractClientHandlerPtr(this)),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SIGNAL(claimFinished())));
+
+ context->setFinished();
+ QTimer::singleShot(0, this, SIGNAL(addDispatchOperationFinished()));
+ }
+
+ bool bypassApproval() const
+ {
+ return mBypassApproval;
+ }
+
+ void handleChannels(const MethodInvocationContextPtr<> &context,
+ const AccountPtr &account,
+ const ConnectionPtr &connection,
+ const QList<ChannelPtr> &channels,
+ const QList<ChannelRequestPtr> &requestsSatisfied,
+ const QDateTime &userActionTime,
+ const AbstractClientHandler::HandlerInfo &handlerInfo)
+ {
+ mHandleChannelsAccount = account;
+ mHandleChannelsConnection = connection;
+ mHandleChannelsChannels = channels;
+ mHandleChannelsRequestsSatisfied = requestsSatisfied;
+ mHandleChannelsUserActionTime = userActionTime;
+ mHandleChannelsHandlerInfo = handlerInfo;
+
+ Q_FOREACH (const ChannelPtr &channel, channels) {
+ connect(channel.data(),
+ SIGNAL(invalidated(Tp::DBusProxy *,
+ const QString &, const QString &)),
+ SIGNAL(channelClosed()));
+ }
+
+ context->setFinished();
+ QTimer::singleShot(0, this, SIGNAL(handleChannelsFinished()));
+ }
+
+ void addRequest(const ChannelRequestPtr &request)
+ {
+ mAddRequestRequest = request;
+ Q_EMIT requestAdded(request);
+ }
+
+ void removeRequest(const ChannelRequestPtr &request,
+ const QString &errorName, const QString &errorMessage)
+ {
+ mRemoveRequestRequest = request;
+ mRemoveRequestErrorName = errorName;
+ mRemoveRequestErrorMessage = errorMessage;
+ Q_EMIT requestRemoved(request, errorName, errorMessage);
+ }
+
+ AccountPtr mObserveChannelsAccount;
+ ConnectionPtr mObserveChannelsConnection;
+ QList<ChannelPtr> mObserveChannelsChannels;
+ ChannelDispatchOperationPtr mObserveChannelsDispatchOperation;
+ QList<ChannelRequestPtr> mObserveChannelsRequestsSatisfied;
+ AbstractClientObserver::ObserverInfo mObserveChannelsObserverInfo;
+
+ QList<ChannelPtr> mAddDispatchOperationChannels;
+ ChannelDispatchOperationPtr mAddDispatchOperationDispatchOperation;
+
+ bool mBypassApproval;
+ AccountPtr mHandleChannelsAccount;
+ ConnectionPtr mHandleChannelsConnection;
+ QList<ChannelPtr> mHandleChannelsChannels;
+ QList<ChannelRequestPtr> mHandleChannelsRequestsSatisfied;
+ QDateTime mHandleChannelsUserActionTime;
+ AbstractClientHandler::HandlerInfo mHandleChannelsHandlerInfo;
+ ChannelRequestPtr mAddRequestRequest;
+ ChannelRequestPtr mRemoveRequestRequest;
+ QString mRemoveRequestErrorName;
+ QString mRemoveRequestErrorMessage;
+
+Q_SIGNALS:
+ void observeChannelsFinished();
+ void addDispatchOperationFinished();
+ void handleChannelsFinished();
+ void claimFinished();
+ void requestAdded(const Tp::ChannelRequestPtr &request);
+ void requestRemoved(const Tp::ChannelRequestPtr &request,
+ const QString &errorName, const QString &errorMessage);
+ void channelClosed();
+};
+
+class TestClient : public Test
+{
+ Q_OBJECT
+
+public:
+ TestClient(QObject *parent = 0)
+ : Test(parent),
+ mConn(0), mContactRepo(0),
+ mText1ChanService(0), mText2ChanService(0), mCDO(0),
+ mClaimFinished(false)
+ { }
+
+ void testObserveChannelsCommon(const AbstractClientPtr &clientObject,
+ const QString &clientBusName, const QString &clientObjectPath);
+
+protected Q_SLOTS:
+ void expectSignalEmission();
+ void onClaimFinished();
+
+private Q_SLOTS:
+ void initTestCase();
+ void init();
+
+ void testRegister();
+ void testCapabilities();
+ void testObserveChannels();
+ void testAddDispatchOperation();
+ void testRequests();
+ void testHandleChannels();
+
+ void cleanup();
+ void cleanupTestCase();
+
+private:
+ AccountManagerPtr mAM;
+ AccountPtr mAccount;
+ TestConnHelper *mConn;
+ TpHandleRepoIface *mContactRepo;
+
+ ExampleEchoChannel *mText1ChanService;
+ ExampleEchoChannel *mText2ChanService;
+ QString mText1ChanPath;
+ QString mText2ChanPath;
+
+ ClientRegistrarPtr mClientRegistrar;
+ QString mChannelDispatcherBusName;
+ QString mChannelRequestPath;
+ ChannelDispatchOperationAdaptor *mCDO;
+ QString mCDOPath;
+ AbstractClientHandler::Capabilities mClientCapabilities;
+ AbstractClientPtr mClientObject1;
+ QString mClientObject1BusName;
+ QString mClientObject1Path;
+ AbstractClientPtr mClientObject2;
+ QString mClientObject2BusName;
+ QString mClientObject2Path;
+ uint mUserActionTime;
+
+ bool mClaimFinished;
+};
+
+void TestClient::expectSignalEmission()
+{
+ mLoop->exit(0);
+}
+
+void TestClient::onClaimFinished()
+{
+ mClaimFinished = true;
+}
+
+void TestClient::initTestCase()
+{
+ initTestCaseImpl();
+
+ g_type_init();
+ g_set_prgname("client");
+ tp_debug_set_flags("all");
+ dbus_g_bus_get(DBUS_BUS_STARTER, 0);
+
+ mAM = AccountManager::create();
+ QVERIFY(connect(mAM->becomeReady(),
+ SIGNAL(finished(Tp::PendingOperation *)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mAM->isReady(), true);
+
+ QVariantMap parameters;
+ parameters[QLatin1String("account")] = QLatin1String("foobar");
+ PendingAccount *pacc = mAM->createAccount(QLatin1String("foo"),
+ QLatin1String("bar"), QLatin1String("foobar"), parameters);
+ QVERIFY(connect(pacc,
+ SIGNAL(finished(Tp::PendingOperation *)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(pacc->account());
+ mAccount = pacc->account();
+
+ mConn = new TestConnHelper(this,
+ TP_TESTS_TYPE_CONTACTS_CONNECTION,
+ "account", "me@example.com",
+ "protocol", "example",
+ NULL);
+ QCOMPARE(mConn->connect(), true);
+
+ mContactRepo = tp_base_connection_get_handles(TP_BASE_CONNECTION(mConn->service()),
+ TP_HANDLE_TYPE_CONTACT);
+ guint handle = tp_handle_ensure(mContactRepo, "someone@localhost", 0, 0);
+
+ // create a Channel by magic, rather than doing D-Bus round-trips for it
+ mText1ChanPath = mConn->objectPath() + QLatin1String("/TextChannel1");
+ QByteArray chanPath(mText1ChanPath.toAscii());
+ mText1ChanService = EXAMPLE_ECHO_CHANNEL(g_object_new(
+ EXAMPLE_TYPE_ECHO_CHANNEL,
+ "connection", mConn->service(),
+ "object-path", chanPath.data(),
+ "handle", handle,
+ NULL));
+
+ mText2ChanPath = mConn->objectPath() + QLatin1String("/TextChannel2");
+ chanPath = mText2ChanPath.toAscii();
+ mText2ChanService = EXAMPLE_ECHO_CHANNEL(g_object_new(
+ EXAMPLE_TYPE_ECHO_CHANNEL,
+ "connection", mConn->service(),
+ "object-path", chanPath.data(),
+ "handle", handle,
+ NULL));
+
+ tp_handle_unref(mContactRepo, handle);
+
+ mClientRegistrar = ClientRegistrar::create();
+
+ QDBusConnection bus = mClientRegistrar->dbusConnection();
+
+ // Fake ChannelRequest
+
+ mChannelDispatcherBusName = QLatin1String(TELEPATHY_INTERFACE_CHANNEL_DISPATCHER);
+ mChannelRequestPath = QLatin1String("/org/freedesktop/Telepathy/ChannelRequest/Request1");
+
+ QObject *request = new QObject(this);
+
+ mUserActionTime = QDateTime::currentDateTime().toTime_t();
+ new ChannelRequestAdaptor(QDBusObjectPath(mAccount->objectPath()),
+ mUserActionTime,
+ QString(),
+ QualifiedPropertyValueMapList(),
+ QStringList(),
+ request);
+ QVERIFY(bus.registerService(mChannelDispatcherBusName));
+ QVERIFY(bus.registerObject(mChannelRequestPath, request));
+
+ // Fake ChannelDispatchOperation
+
+ mCDOPath = QLatin1String("/org/freedesktop/Telepathy/ChannelDispatchOperation/Operation1");
+
+ QObject *cdo = new QObject(this);
+
+ // Initialize this here so we can actually set it in possibleHandlers
+ mClientObject1BusName = QLatin1String("org.freedesktop.Telepathy.Client.foo");
+
+ ChannelDetailsList channelDetailsList;
+ ChannelDetails channelDetails = { QDBusObjectPath(mText1ChanPath), QVariantMap() };
+ channelDetailsList.append(channelDetails);
+
+ mCDO = new ChannelDispatchOperationAdaptor(QDBusObjectPath(mAccount->objectPath()),
+ QDBusObjectPath(mConn->objectPath()), channelDetailsList,
+ QStringList() << mClientObject1BusName, cdo);
+ QVERIFY(bus.registerObject(mCDOPath, cdo));
+}
+
+void TestClient::init()
+{
+ initImpl();
+ mClaimFinished = false;
+}
+
+void TestClient::testRegister()
+{
+ // invalid client
+ QVERIFY(!mClientRegistrar->registerClient(AbstractClientPtr(), QLatin1String("foo")));
+
+ mClientCapabilities.setICEUDPNATTraversalToken();
+ mClientCapabilities.setToken(TP_QT4_IFACE_CHANNEL_INTERFACE_MEDIA_SIGNALLING +
+ QLatin1String("/audio/speex=true"));
+
+ ChannelClassSpecList filters;
+ filters.append(ChannelClassSpec::textChat());
+ mClientObject1 = MyClient::create(filters, mClientCapabilities, false, true);
+ MyClient *client = dynamic_cast<MyClient*>(mClientObject1.data());
+ QVERIFY(!client->isRegistered());
+ QVERIFY(mClientRegistrar->registerClient(mClientObject1, QLatin1String("foo")));
+ QVERIFY(client->isRegistered());
+ QVERIFY(mClientRegistrar->registeredClients().contains(mClientObject1));
+
+ AbstractClientPtr clientObjectRedundant = MyClient::create(
+ filters, mClientCapabilities, false, true);
+ client = dynamic_cast<MyClient*>(clientObjectRedundant.data());
+ QVERIFY(!client->isRegistered());
+ // try to register using a name already registered and a different object, it should fail
+ // and not report isRegistered
+ QVERIFY(!mClientRegistrar->registerClient(clientObjectRedundant, QLatin1String("foo")));
+ QVERIFY(!client->isRegistered());
+ QVERIFY(!mClientRegistrar->registeredClients().contains(clientObjectRedundant));
+
+ client = dynamic_cast<MyClient*>(mClientObject1.data());
+
+ // no op - client already registered with same object and name
+ QVERIFY(mClientRegistrar->registerClient(mClientObject1, QLatin1String("foo")));
+
+ // unregister client
+ QVERIFY(mClientRegistrar->unregisterClient(mClientObject1));
+ QVERIFY(!client->isRegistered());
+
+ // register again
+ QVERIFY(mClientRegistrar->registerClient(mClientObject1, QLatin1String("foo")));
+ QVERIFY(client->isRegistered());
+
+ filters.clear();
+ filters.append(ChannelClassSpec::streamedMediaCall());
+ mClientObject2 = MyClient::create(filters, mClientCapabilities, true, true);
+ QVERIFY(mClientRegistrar->registerClient(mClientObject2, QLatin1String("foo"), true));
+ QVERIFY(mClientRegistrar->registeredClients().contains(mClientObject2));
+
+ // no op - client already registered
+ QVERIFY(mClientRegistrar->registerClient(mClientObject2, QLatin1String("foo"), true));
+
+ QDBusConnection bus = mClientRegistrar->dbusConnection();
+ QDBusConnectionInterface *busIface = bus.interface();
+ QStringList registeredServicesNames = busIface->registeredServiceNames();
+ QVERIFY(registeredServicesNames.filter(
+ QRegExp(QLatin1String("^" "org.freedesktop.Telepathy.Client.foo"
+ ".([_A-Za-z][_A-Za-z0-9]*)"))).size() == 1);
+
+ mClientObject1BusName = QLatin1String("org.freedesktop.Telepathy.Client.foo");
+ mClientObject1Path = QLatin1String("/org/freedesktop/Telepathy/Client/foo");
+
+ mClientObject2BusName = registeredServicesNames.filter(
+ QRegExp(QLatin1String("org.freedesktop.Telepathy.Client.foo._*"))).first();
+ mClientObject2Path = QString(QLatin1String("/%1")).arg(mClientObject2BusName);
+ mClientObject2Path.replace(QLatin1String("."), QLatin1String("/"));
+}
+
+void TestClient::testCapabilities()
+{
+ QDBusConnection bus = mClientRegistrar->dbusConnection();
+ QStringList normalizedClientCaps = mClientCapabilities.allTokens();
+ normalizedClientCaps.sort();
+
+ QStringList normalizedHandlerCaps;
+
+ // object 1
+ ClientHandlerInterface *handler1Iface = new ClientHandlerInterface(bus,
+ mClientObject1BusName, mClientObject1Path, this);
+
+ QVERIFY(waitForProperty(handler1Iface->requestPropertyCapabilities(), &normalizedHandlerCaps));
+ normalizedHandlerCaps.sort();
+ QCOMPARE(normalizedHandlerCaps, normalizedClientCaps);
+
+ // object 2
+ ClientHandlerInterface *handler2Iface = new ClientHandlerInterface(bus,
+ mClientObject2BusName, mClientObject2Path, this);
+
+ QVERIFY(waitForProperty(handler2Iface->requestPropertyCapabilities(), &normalizedHandlerCaps));
+ normalizedHandlerCaps.sort();
+ QCOMPARE(normalizedHandlerCaps, normalizedClientCaps);
+}
+
+void TestClient::testRequests()
+{
+ QDBusConnection bus = mClientRegistrar->dbusConnection();
+ ClientInterfaceRequestsInterface *handlerRequestsIface = new ClientInterfaceRequestsInterface(bus,
+ mClientObject1BusName, mClientObject1Path, this);
+
+ MyClient *client = dynamic_cast<MyClient*>(mClientObject1.data());
+ connect(client,
+ SIGNAL(requestAdded(const Tp::ChannelRequestPtr &)),
+ SLOT(expectSignalEmission()));
+ handlerRequestsIface->AddRequest(QDBusObjectPath(mChannelRequestPath), QVariantMap());
+ if (!client->mAddRequestRequest) {
+ QCOMPARE(mLoop->exec(), 0);
+ }
+ QCOMPARE(client->mAddRequestRequest->objectPath(),
+ mChannelRequestPath);
+
+ connect(client,
+ SIGNAL(requestRemoved(const Tp::ChannelRequestPtr &,
+ const QString &,
+ const QString &)),
+ SLOT(expectSignalEmission()));
+ handlerRequestsIface->RemoveRequest(QDBusObjectPath(mChannelRequestPath),
+ QLatin1String(TELEPATHY_ERROR_NOT_AVAILABLE),
+ QLatin1String("Not available"));
+ if (!client->mRemoveRequestRequest) {
+ QCOMPARE(mLoop->exec(), 0);
+ }
+ QCOMPARE(client->mRemoveRequestRequest->objectPath(),
+ mChannelRequestPath);
+ QCOMPARE(client->mRemoveRequestErrorName,
+ QString(QLatin1String(TELEPATHY_ERROR_NOT_AVAILABLE)));
+ QCOMPARE(client->mRemoveRequestErrorMessage,
+ QString(QLatin1String("Not available")));
+}
+
+void TestClient::testObserveChannelsCommon(const AbstractClientPtr &clientObject,
+ const QString &clientBusName, const QString &clientObjectPath)
+{
+ QDBusConnection bus = mClientRegistrar->dbusConnection();
+
+ ClientObserverInterface *observeIface = new ClientObserverInterface(bus,
+ clientBusName, clientObjectPath, this);
+ MyClient *client = dynamic_cast<MyClient*>(clientObject.data());
+ connect(client,
+ SIGNAL(observeChannelsFinished()),
+ SLOT(expectSignalEmission()));
+ ChannelDetailsList channelDetailsList;
+ ChannelDetails channelDetails = { QDBusObjectPath(mText1ChanPath), QVariantMap() };
+ channelDetailsList.append(channelDetails);
+
+ QVariantMap observerInfo;
+ ObjectImmutablePropertiesMap reqPropsMap;
+ QVariantMap channelReqImmutableProps;
+ channelReqImmutableProps.insert(
+ QLatin1String(
+ TELEPATHY_INTERFACE_CHANNEL_REQUEST ".Interface.DomainSpecific.IntegerProp"), 3);
+ channelReqImmutableProps.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL_REQUEST ".Account"),
+ qVariantFromValue(QDBusObjectPath(mAccount->objectPath())));
+ reqPropsMap.insert(QDBusObjectPath(mChannelRequestPath), channelReqImmutableProps);
+ observerInfo.insert(QLatin1String("request-properties"), qVariantFromValue(reqPropsMap));
+ observeIface->ObserveChannels(QDBusObjectPath(mAccount->objectPath()),
+ QDBusObjectPath(mConn->objectPath()),
+ channelDetailsList,
+ QDBusObjectPath("/"),
+ ObjectPathList() << QDBusObjectPath(mChannelRequestPath),
+ observerInfo);
+ QCOMPARE(mLoop->exec(), 0);
+
+ QCOMPARE(client->mObserveChannelsAccount->objectPath(), mAccount->objectPath());
+ QCOMPARE(client->mObserveChannelsConnection->objectPath(), mConn->objectPath());
+ QCOMPARE(client->mObserveChannelsChannels.first()->objectPath(), mText1ChanPath);
+ QVERIFY(client->mObserveChannelsDispatchOperation.isNull());
+ QCOMPARE(client->mObserveChannelsRequestsSatisfied.first()->objectPath(), mChannelRequestPath);
+ QCOMPARE(client->mObserveChannelsRequestsSatisfied.first()->immutableProperties().contains(
+ QLatin1String(
+ TELEPATHY_INTERFACE_CHANNEL_REQUEST ".Interface.DomainSpecific.IntegerProp")), true);
+ QCOMPARE(qdbus_cast<int>(client->mObserveChannelsRequestsSatisfied.first()->immutableProperties().value(
+ QLatin1String(
+ TELEPATHY_INTERFACE_CHANNEL_REQUEST ".Interface.DomainSpecific.IntegerProp"))), 3);
+}
+
+void TestClient::testObserveChannels()
+{
+ testObserveChannelsCommon(mClientObject1,
+ mClientObject1BusName, mClientObject1Path);
+ testObserveChannelsCommon(mClientObject2,
+ mClientObject2BusName, mClientObject2Path);
+}
+
+void TestClient::testAddDispatchOperation()
+{
+ QDBusConnection bus = mClientRegistrar->dbusConnection();
+
+ ClientApproverInterface *approverIface = new ClientApproverInterface(bus,
+ mClientObject1BusName, mClientObject1Path, this);
+ ClientHandlerInterface *handler1Iface = new ClientHandlerInterface(bus,
+ mClientObject1BusName, mClientObject1Path, this);
+ MyClient *client = dynamic_cast<MyClient*>(mClientObject1.data());
+ connect(client,
+ SIGNAL(addDispatchOperationFinished()),
+ SLOT(expectSignalEmission()));
+ connect(client,
+ SIGNAL(claimFinished()),
+ SLOT(onClaimFinished()));
+
+ QVariantMap dispatchOperationProperties;
+ dispatchOperationProperties.insert(
+ QLatin1String(TELEPATHY_INTERFACE_CHANNEL_DISPATCH_OPERATION ".Connection"),
+ QVariant::fromValue(QDBusObjectPath(mConn->objectPath())));
+ dispatchOperationProperties.insert(
+ QLatin1String(TELEPATHY_INTERFACE_CHANNEL_DISPATCH_OPERATION ".Account"),
+ QVariant::fromValue(QDBusObjectPath(mAccount->objectPath())));
+ dispatchOperationProperties.insert(
+ QLatin1String(TELEPATHY_INTERFACE_CHANNEL_DISPATCH_OPERATION ".PossibleHandlers"),
+ QVariant::fromValue(ObjectPathList() << QDBusObjectPath(mClientObject1Path)
+ << QDBusObjectPath(mClientObject2Path)));
+
+ // Handler.HandledChannels should be empty here, CDO::claim(handler) will populate it on
+ // success
+ Tp::ObjectPathList handledChannels;
+ QVERIFY(waitForProperty(handler1Iface->requestPropertyHandledChannels(), &handledChannels));
+ QVERIFY(handledChannels.isEmpty());
+
+ approverIface->AddDispatchOperation(mCDO->Channels(), QDBusObjectPath(mCDOPath),
+ dispatchOperationProperties);
+ QCOMPARE(mLoop->exec(), 0);
+ while (!mClaimFinished) {
+ mLoop->processEvents();
+ }
+
+ QCOMPARE(client->mAddDispatchOperationChannels.first()->objectPath(), mText1ChanPath);
+ QCOMPARE(client->mAddDispatchOperationDispatchOperation->objectPath(), mCDOPath);
+
+ // Claim finished, Handler.HandledChannels should be populated now
+ handledChannels.clear();
+ QVERIFY(waitForProperty(handler1Iface->requestPropertyHandledChannels(), &handledChannels));
+ QVERIFY(!handledChannels.isEmpty());
+ qSort(handledChannels);
+ Tp::ObjectPathList expectedHandledChannels;
+ Q_FOREACH (const ChannelDetails &details, mCDO->Channels()) {
+ expectedHandledChannels << details.channel;
+ }
+ qSort(expectedHandledChannels);
+ QCOMPARE(handledChannels, expectedHandledChannels);
+}
+
+void TestClient::testHandleChannels()
+{
+ QDBusConnection bus = mClientRegistrar->dbusConnection();
+
+ // object 1
+ ClientHandlerInterface *handler1Iface = new ClientHandlerInterface(bus,
+ mClientObject1BusName, mClientObject1Path, this);
+ MyClient *client1 = dynamic_cast<MyClient*>(mClientObject1.data());
+ connect(client1,
+ SIGNAL(handleChannelsFinished()),
+ SLOT(expectSignalEmission()));
+ ChannelDetailsList channelDetailsList;
+ ChannelDetails channelDetails = { QDBusObjectPath(mText1ChanPath), QVariantMap() };
+ channelDetailsList.append(channelDetails);
+ handler1Iface->HandleChannels(QDBusObjectPath(mAccount->objectPath()),
+ QDBusObjectPath(mConn->objectPath()),
+ channelDetailsList,
+ ObjectPathList() << QDBusObjectPath(mChannelRequestPath),
+ mUserActionTime,
+ QVariantMap());
+ QCOMPARE(mLoop->exec(), 0);
+
+ QCOMPARE(client1->mHandleChannelsAccount->objectPath(), mAccount->objectPath());
+ QCOMPARE(client1->mHandleChannelsConnection->objectPath(), mConn->objectPath());
+ QCOMPARE(client1->mHandleChannelsChannels.first()->objectPath(), mText1ChanPath);
+ QCOMPARE(client1->mHandleChannelsRequestsSatisfied.first()->objectPath(), mChannelRequestPath);
+ QCOMPARE(client1->mHandleChannelsUserActionTime.toTime_t(), mUserActionTime);
+
+ Tp::ObjectPathList handledChannels;
+ QVERIFY(waitForProperty(handler1Iface->requestPropertyHandledChannels(), &handledChannels));
+ QVERIFY(handledChannels.contains(QDBusObjectPath(mText1ChanPath)));
+
+ // object 2
+ ClientHandlerInterface *handler2Iface = new ClientHandlerInterface(bus,
+ mClientObject2BusName, mClientObject2Path, this);
+ MyClient *client2 = dynamic_cast<MyClient*>(mClientObject2.data());
+ connect(client2,
+ SIGNAL(handleChannelsFinished()),
+ SLOT(expectSignalEmission()));
+ channelDetailsList.clear();
+ channelDetails.channel = QDBusObjectPath(mText2ChanPath);
+ channelDetailsList.append(channelDetails);
+ handler2Iface->HandleChannels(QDBusObjectPath(mAccount->objectPath()),
+ QDBusObjectPath(mConn->objectPath()),
+ channelDetailsList,
+ ObjectPathList() << QDBusObjectPath(mChannelRequestPath),
+ mUserActionTime,
+ QVariantMap());
+ QCOMPARE(mLoop->exec(), 0);
+
+ QCOMPARE(client2->mHandleChannelsAccount->objectPath(), mAccount->objectPath());
+ QCOMPARE(client2->mHandleChannelsConnection->objectPath(), mConn->objectPath());
+ QCOMPARE(client2->mHandleChannelsChannels.first()->objectPath(), mText2ChanPath);
+ QCOMPARE(client2->mHandleChannelsRequestsSatisfied.first()->objectPath(), mChannelRequestPath);
+ QCOMPARE(client2->mHandleChannelsUserActionTime.toTime_t(), mUserActionTime);
+
+ QVERIFY(waitForProperty(handler1Iface->requestPropertyHandledChannels(), &handledChannels));
+ QVERIFY(handledChannels.contains(QDBusObjectPath(mText1ChanPath)));
+ QVERIFY(handledChannels.contains(QDBusObjectPath(mText2ChanPath)));
+
+ QVERIFY(waitForProperty(handler2Iface->requestPropertyHandledChannels(), &handledChannels));
+ QVERIFY(handledChannels.contains(QDBusObjectPath(mText1ChanPath)));
+ QVERIFY(handledChannels.contains(QDBusObjectPath(mText2ChanPath)));
+
+ // Handler.HandledChannels will now return all channels that are not invalidated/destroyed
+ // even if the handler for such channels was already unregistered
+ g_object_unref(mText1ChanService);
+ connect(client1,
+ SIGNAL(channelClosed()),
+ SLOT(expectSignalEmission()));
+ QCOMPARE(mLoop->exec(), 0);
+
+ mClientRegistrar->unregisterClient(mClientObject1);
+ QVERIFY(waitForProperty(handler2Iface->requestPropertyHandledChannels(), &handledChannels));
+ QVERIFY(handledChannels.contains(QDBusObjectPath(mText2ChanPath)));
+
+ g_object_unref(mText2ChanService);
+ connect(client2,
+ SIGNAL(channelClosed()),
+ SLOT(expectSignalEmission()));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(waitForProperty(handler2Iface->requestPropertyHandledChannels(), &handledChannels));
+ QVERIFY(handledChannels.isEmpty());
+}
+
+void TestClient::cleanup()
+{
+ cleanupImpl();
+}
+
+void TestClient::cleanupTestCase()
+{
+ if (mConn) {
+ QCOMPARE(mConn->disconnect(), true);
+ delete mConn;
+ }
+
+ cleanupTestCaseImpl();
+}
+
+QTEST_MAIN(TestClient)
+#include "_gen/client.cpp.moc.hpp"