1
#include <QtCore/QDebug>
2
#include <QtCore/QTimer>
3
#include <QtDBus/QtDBus>
4
#include <QtTest/QtTest>
10
#include <TelepathyQt/Connection>
11
#include <TelepathyQt/ConnectionFactory>
12
#include <TelepathyQt/ContactFactory>
13
#include <TelepathyQt/ChannelFactory>
14
#include <TelepathyQt/Debug>
15
#include <TelepathyQt/PendingReady>
16
#include <TelepathyQt/Types>
18
#include <TelepathyQt/test-backdoors.h>
20
#include <telepathy-glib/debug.h>
22
#include <glib-object.h>
23
#include <dbus/dbus-glib.h>
25
#include <tests/lib/glib/contacts-conn.h>
26
#include <tests/lib/test.h>
30
class TestDBusProxyFactory : public Test
35
TestDBusProxyFactory(QObject *parent = 0)
37
mConnService1(0), mConnService2(0)
41
void expectFinished();
49
void testInvalidate();
50
void testBogusService();
53
void cleanupTestCase();
56
TpTestsContactsConnection *mConnService1, *mConnService2;
57
QString mConnPath1, mConnPath2;
58
QString mConnName1, mConnName2;
59
ConnectionFactoryPtr mFactory;
63
void TestDBusProxyFactory::expectFinished()
68
void TestDBusProxyFactory::initTestCase()
73
g_set_prgname("dbus-proxy-factory");
74
tp_debug_set_flags("all");
75
dbus_g_bus_get(DBUS_BUS_STARTER, 0);
81
mConnService1 = TP_TESTS_CONTACTS_CONNECTION(g_object_new(
82
TP_TESTS_TYPE_CONTACTS_CONNECTION,
83
"account", "me1@example.com",
86
QVERIFY(mConnService1 != 0);
87
QVERIFY(tp_base_connection_register(TP_BASE_CONNECTION(mConnService1),
88
"contacts", &name, &connPath, &error));
92
QVERIFY(connPath != 0);
94
mConnName1 = QLatin1String(name);
95
mConnPath1 = QLatin1String(connPath);
100
mConnService2 = TP_TESTS_CONTACTS_CONNECTION(g_object_new(
101
TP_TESTS_TYPE_CONTACTS_CONNECTION,
102
"account", "me2@example.com",
103
"protocol", "simple",
105
QVERIFY(mConnService2 != 0);
106
QVERIFY(tp_base_connection_register(TP_BASE_CONNECTION(mConnService2),
107
"contacts", &name, &connPath, &error));
111
QVERIFY(connPath != 0);
113
mConnName2 = QLatin1String(name);
114
mConnPath2 = QLatin1String(connPath);
120
void TestDBusProxyFactory::init()
124
mFactory = ConnectionFactory::create(QDBusConnection::sessionBus(),
125
Connection::FeatureCore);
129
void TestDBusProxyFactory::testCaching()
131
PendingReady *first = mFactory->proxy(mConnName1, mConnPath1,
132
ChannelFactory::create(QDBusConnection::sessionBus()),
133
ContactFactory::create());
135
QVERIFY(first != NULL);
136
QVERIFY(!first->proxy().isNull());
138
PendingReady *same = mFactory->proxy(mConnName1, mConnPath1,
139
ChannelFactory::create(QDBusConnection::sessionBus()),
140
ContactFactory::create());
142
QVERIFY(same != NULL);
143
QVERIFY(!same->proxy().isNull());
145
QCOMPARE(same->proxy().data(), first->proxy().data());
147
PendingReady *different = mFactory->proxy(mConnName2, mConnPath2,
148
ChannelFactory::create(QDBusConnection::sessionBus()),
149
ContactFactory::create());
151
QVERIFY(different != NULL);
152
QVERIFY(!different->proxy().isNull());
154
QVERIFY(different->proxy() != first->proxy());
156
ConnectionPtr firstProxy = ConnectionPtr::qObjectCast(first->proxy());
158
QVERIFY(!first->isFinished() && !same->isFinished() && !different->isFinished());
159
QVERIFY(connect(first, SIGNAL(finished(Tp::PendingOperation*)),
160
SLOT(expectFinished())));
161
QVERIFY(connect(same, SIGNAL(finished(Tp::PendingOperation*)),
162
SLOT(expectFinished())));
163
QVERIFY(connect(different, SIGNAL(finished(Tp::PendingOperation*)),
164
SLOT(expectFinished())));
165
QVERIFY(!first->isFinished() && !same->isFinished() && !different->isFinished());
167
while (mNumFinished < 3) {
168
mLoop->processEvents();
171
QCOMPARE(mNumFinished, 3U);
173
PendingReady *another = mFactory->proxy(mConnName1, mConnPath1,
174
ChannelFactory::create(QDBusConnection::sessionBus()),
175
ContactFactory::create());
177
QVERIFY(another != NULL);
178
QVERIFY(!another->proxy().isNull());
180
// Should still be the same even if all the initial requests already finished
181
QCOMPARE(another->proxy().data(), firstProxy.data());
183
QVERIFY(connect(another, SIGNAL(finished(Tp::PendingOperation*)),
184
SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
185
QCOMPARE(mLoop->exec(), 0);
188
void TestDBusProxyFactory::testDropRefs()
190
PendingReady *first = mFactory->proxy(mConnName1, mConnPath1,
191
ChannelFactory::create(QDBusConnection::sessionBus()),
192
ContactFactory::create());
194
QVERIFY(first != NULL);
195
QVERIFY(!first->proxy().isNull());
197
ConnectionPtr firstProxy = ConnectionPtr::qObjectCast(first->proxy());
198
QVERIFY(firstProxy->isValid());
200
QVERIFY(connect(first, SIGNAL(finished(Tp::PendingOperation*)),
201
SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
202
QCOMPARE(mLoop->exec(), 0);
204
PendingReady *same = mFactory->proxy(mConnName1, mConnPath1,
205
ChannelFactory::create(QDBusConnection::sessionBus()),
206
ContactFactory::create());
208
QVERIFY(same != NULL);
209
QVERIFY(!same->proxy().isNull());
211
// The first one is in scope so we should've got it again
212
QCOMPARE(same->proxy().data(), firstProxy.data());
214
QVERIFY(connect(same, SIGNAL(finished(Tp::PendingOperation*)),
215
SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
216
QCOMPARE(mLoop->exec(), 0);
218
// Flush the delete event for the PendingReady, which drops the PendingReady ref to the proxy
219
mLoop->processEvents();
221
// Make the Conn go out of scope
222
Connection *firstPtr = firstProxy.data();
225
PendingReady *different = mFactory->proxy(mConnName1, mConnPath1,
226
ChannelFactory::create(QDBusConnection::sessionBus()),
227
ContactFactory::create());
229
QVERIFY(different != NULL);
230
QVERIFY(!different->proxy().isNull());
232
// The first one has gone out of scope and deleted so we should've got a different one
233
QVERIFY(different->proxy().data() != firstPtr);
236
void TestDBusProxyFactory::testInvalidate()
238
PendingReady *first = mFactory->proxy(mConnName1, mConnPath1,
239
ChannelFactory::create(QDBusConnection::sessionBus()),
240
ContactFactory::create());
242
QVERIFY(first != NULL);
243
QVERIFY(!first->proxy().isNull());
245
ConnectionPtr firstProxy = ConnectionPtr::qObjectCast(first->proxy());
246
QVERIFY(firstProxy->isValid());
248
QVERIFY(connect(first, SIGNAL(finished(Tp::PendingOperation*)),
249
SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
250
QCOMPARE(mLoop->exec(), 0);
252
PendingReady *same = mFactory->proxy(mConnName1, mConnPath1,
253
ChannelFactory::create(QDBusConnection::sessionBus()),
254
ContactFactory::create());
256
QVERIFY(same != NULL);
257
QVERIFY(!same->proxy().isNull());
259
// The first one is in scope and valid so we should've got it again
260
QCOMPARE(same->proxy().data(), firstProxy.data());
262
QVERIFY(connect(same, SIGNAL(finished(Tp::PendingOperation*)),
263
SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
264
QCOMPARE(mLoop->exec(), 0);
266
// Flush the delete event for the PendingReady, which drops the PendingReady ref to the proxy
267
mLoop->processEvents();
269
// Synthesize an invalidation for the proxy
270
QVERIFY(connect(firstProxy.data(), SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
271
mLoop, SLOT(quit())));
272
TestBackdoors::invalidateProxy(firstProxy.data(),
273
QLatin1String("im.bonghits.Errors.Synthetic"), QLatin1String(""));
274
QCOMPARE(mLoop->exec(), 0);
276
QVERIFY(!firstProxy->isValid());
278
PendingReady *different = mFactory->proxy(mConnName1, mConnPath1,
279
ChannelFactory::create(QDBusConnection::sessionBus()),
280
ContactFactory::create());
282
QVERIFY(different != NULL);
283
ConnectionPtr differentProxy = ConnectionPtr::qObjectCast(different->proxy());
284
QVERIFY(!differentProxy.isNull());
286
// The first one is invalid so we should've got a different one
287
QVERIFY(differentProxy.data() != firstProxy.data());
288
QVERIFY(differentProxy->isValid());
290
QVERIFY(!differentProxy->isReady());
292
QVERIFY(connect(different,
293
SIGNAL(finished(Tp::PendingOperation*)),
294
SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
295
QCOMPARE(mLoop->exec(), 0);
297
QVERIFY(differentProxy->isValid());
298
QVERIFY(differentProxy->isReady());
301
void TestDBusProxyFactory::testBogusService()
303
PendingReady *bogus = mFactory->proxy(QLatin1String("org.bogus.Totally"),
304
QLatin1String("/org/bogus/Totally"),
305
ChannelFactory::create(QDBusConnection::sessionBus()),
306
ContactFactory::create());
308
QVERIFY(bogus != NULL);
309
QVERIFY(!bogus->proxy().isNull());
311
QVERIFY(!ConnectionPtr::qObjectCast(bogus->proxy())->isValid());
313
PendingReady *another = mFactory->proxy(QLatin1String("org.bogus.Totally"),
314
QLatin1String("/org/bogus/Totally"),
315
ChannelFactory::create(QDBusConnection::sessionBus()),
316
ContactFactory::create());
318
QVERIFY(another != NULL);
319
QVERIFY(!another->proxy().isNull());
321
QVERIFY(!ConnectionPtr::qObjectCast(another->proxy())->isValid());
323
// We shouldn't get the same proxy twice ie. a proxy should not be cached if not present on bus
324
// and invalidated because of that, otherwise we'll return an invalid instance from the cache
325
// even if after the service appears on the bus
326
QVERIFY(another->proxy() != bogus->proxy());
328
// The PendingReady itself should finish with failure
329
QVERIFY(connect(another, SIGNAL(finished(Tp::PendingOperation*)),
330
SLOT(expectFailure(Tp::PendingOperation*))));
331
QCOMPARE(mLoop->exec(), 0);
334
void TestDBusProxyFactory::cleanup()
341
void TestDBusProxyFactory::cleanupTestCase()
343
cleanupTestCaseImpl();
346
QTEST_MAIN(TestDBusProxyFactory)
347
#include "_gen/dbus-proxy-factory.cpp.moc.hpp"