1 #include <QtCore/QDebug>
2 #include <QtCore/QTimer>
3
4 #include <QtDBus/QtDBus>
5
6 #include <QtTest/QtTest>
7
8 #define TP_QT_ENABLE_LOWLEVEL_API
9
10 #include <TelepathyQt/ChannelFactory>
11 #include <TelepathyQt/Connection>
12 #include <TelepathyQt/ConnectionLowlevel>
13 #include <TelepathyQt/ContactFactory>
14 #include <TelepathyQt/PendingChannel>
15 #include <TelepathyQt/PendingReady>
16 #include <TelepathyQt/Debug>
17
18 #include <telepathy-glib/dbus.h>
19 #include <telepathy-glib/debug.h>
20
21 #include <tests/lib/glib/contacts-conn.h>
22 #include <tests/lib/test.h>
23
24 using namespace Tp;
25
26 class TestConnBasics : public Test
27 {
28 Q_OBJECT
29
30 public:
TestConnBasics(QObject * parent=0)31 TestConnBasics(QObject *parent = 0)
32 : Test(parent), mConnService(0)
33 { }
34
35 protected Q_SLOTS:
36 void expectConnReady(Tp::ConnectionStatus);
37 void expectConnInvalidated();
38 void expectPresenceAvailable(const Tp::SimplePresence &);
39 void onRequestConnectFinished(Tp::PendingOperation *);
40
41 private Q_SLOTS:
42 void initTestCase();
43 void init();
44
45 void testBasics();
46 void testSimplePresence();
47
48 void cleanup();
49 void cleanupTestCase();
50
51 private:
52 QString mConnName, mConnPath;
53 TpTestsContactsConnection *mConnService;
54 ConnectionPtr mConn;
55 QList<ConnectionStatus> mStatuses;
56 };
57
expectConnReady(Tp::ConnectionStatus newStatus)58 void TestConnBasics::expectConnReady(Tp::ConnectionStatus newStatus)
59 {
60 qDebug() << "connection changed to status" << newStatus;
61 switch (newStatus) {
62 case ConnectionStatusDisconnected:
63 qWarning() << "Disconnected";
64 break;
65 case ConnectionStatusConnecting:
66 QCOMPARE(mConn->isReady(Connection::FeatureConnected), false);
67 mStatuses << newStatus;
68 qDebug() << "Connecting";
69 break;
70 case ConnectionStatusConnected:
71 QCOMPARE(mConn->isReady(Connection::FeatureConnected), true);
72 mStatuses << newStatus;
73 qDebug() << "Connected";
74 break;
75 default:
76 qWarning().nospace() << "What sort of status is "
77 << newStatus << "?!";
78 break;
79 }
80 }
81
expectConnInvalidated()82 void TestConnBasics::expectConnInvalidated()
83 {
84 qDebug() << "conn invalidated";
85
86 mLoop->exit(0);
87 }
88
expectPresenceAvailable(const Tp::SimplePresence & presence)89 void TestConnBasics::expectPresenceAvailable(const Tp::SimplePresence &presence)
90 {
91 if (presence.type == Tp::ConnectionPresenceTypeAvailable) {
92 mLoop->exit(0);
93 return;
94 }
95 mLoop->exit(1);
96 }
97
onRequestConnectFinished(Tp::PendingOperation * op)98 void TestConnBasics::onRequestConnectFinished(Tp::PendingOperation *op)
99 {
100 QCOMPARE(mConn->status(), ConnectionStatusConnected);
101 QVERIFY(mStatuses.contains(ConnectionStatusConnected));
102 mLoop->exit(0);
103 }
104
initTestCase()105 void TestConnBasics::initTestCase()
106 {
107 initTestCaseImpl();
108
109 g_type_init();
110 g_set_prgname("conn-basics");
111 tp_debug_set_flags("all");
112 dbus_g_bus_get(DBUS_BUS_STARTER, 0);
113 }
114
init()115 void TestConnBasics::init()
116 {
117 initImpl();
118
119 gchar *name;
120 gchar *connPath;
121 GError *error = 0;
122
123 mConnService = TP_TESTS_CONTACTS_CONNECTION(g_object_new(
124 TP_TESTS_TYPE_CONTACTS_CONNECTION,
125 "account", "me@example.com",
126 "protocol", "contacts",
127 NULL));
128 QVERIFY(mConnService != 0);
129 QVERIFY(tp_base_connection_register(TP_BASE_CONNECTION(mConnService),
130 "contacts", &name, &connPath, &error));
131 QVERIFY(error == 0);
132
133 QVERIFY(name != 0);
134 QVERIFY(connPath != 0);
135
136 mConnName = QLatin1String(name);
137 mConnPath = QLatin1String(connPath);
138
139 g_free(name);
140 g_free(connPath);
141
142 mConn = Connection::create(mConnName, mConnPath,
143 ChannelFactory::create(QDBusConnection::sessionBus()),
144 ContactFactory::create());
145 QCOMPARE(mConn->isReady(), false);
146
147 QVERIFY(connect(mConn.data(),
148 SIGNAL(statusChanged(Tp::ConnectionStatus)),
149 SLOT(expectConnReady(Tp::ConnectionStatus))));
150
151 qDebug() << "waiting connection to become connected";
152 PendingOperation *pr = mConn->becomeReady(Connection::FeatureConnected);
153 QVERIFY(connect(pr,
154 SIGNAL(finished(Tp::PendingOperation*)),
155 SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
156
157 PendingOperation *pc = mConn->lowlevel()->requestConnect();
158 QVERIFY(connect(pc,
159 SIGNAL(finished(Tp::PendingOperation*)),
160 SLOT(onRequestConnectFinished(Tp::PendingOperation*))));
161 QCOMPARE(mLoop->exec(), 0);
162 QCOMPARE(pr->isFinished(), true);
163 QCOMPARE(mLoop->exec(), 0);
164 QCOMPARE(pc->isFinished(), true);
165 QCOMPARE(mConn->isReady(Connection::FeatureConnected), true);
166 qDebug() << "connection is now ready";
167
168 QVERIFY(disconnect(mConn.data(),
169 SIGNAL(statusChanged(Tp::ConnectionStatus)),
170 this,
171 SLOT(expectConnReady(Tp::ConnectionStatus))));
172 }
173
testBasics()174 void TestConnBasics::testBasics()
175 {
176 QCOMPARE(static_cast<uint>(mConn->statusReason()),
177 static_cast<uint>(ConnectionStatusReasonRequested));
178 }
179
testSimplePresence()180 void TestConnBasics::testSimplePresence()
181 {
182 qDebug() << "Making SimplePresence ready";
183
184 Features features = Features() << Connection::FeatureSimplePresence;
185 QCOMPARE(mConn->isReady(features), false);
186 QVERIFY(connect(mConn->becomeReady(features),
187 SIGNAL(finished(Tp::PendingOperation*)),
188 SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
189 QCOMPARE(mLoop->exec(), 0);
190 QCOMPARE(mConn->isReady(features), true);
191
192 qDebug() << "SimplePresence ready";
193 qDebug() << "mConn->status:" << mConn->status();
194
195 const QStringList canSetNames = QStringList()
196 << QLatin1String("available")
197 << QLatin1String("busy")
198 << QLatin1String("away");
199
200 const QStringList cantSetNames = QStringList()
201 << QLatin1String("offline")
202 << QLatin1String("unknown")
203 << QLatin1String("error");
204
205 const QStringList expectedNames = canSetNames + cantSetNames;
206
207 const ConnectionPresenceType expectedTypes[] = {
208 ConnectionPresenceTypeAvailable,
209 ConnectionPresenceTypeBusy,
210 ConnectionPresenceTypeAway,
211 ConnectionPresenceTypeOffline,
212 ConnectionPresenceTypeUnknown,
213 ConnectionPresenceTypeError
214 };
215
216 SimpleStatusSpecMap statuses = mConn->lowlevel()->allowedPresenceStatuses();
217 Q_FOREACH (QString name, statuses.keys()) {
218 QVERIFY(expectedNames.contains(name));
219
220 if (canSetNames.contains(name)) {
221 QVERIFY(statuses[name].maySetOnSelf);
222 QVERIFY(statuses[name].canHaveMessage);
223 } else {
224 QVERIFY(cantSetNames.contains(name));
225 QVERIFY(!statuses[name].maySetOnSelf);
226 QVERIFY(!statuses[name].canHaveMessage);
227 }
228
229 QCOMPARE(statuses[name].type,
230 static_cast<uint>(expectedTypes[expectedNames.indexOf(name)]));
231 }
232
233 QCOMPARE(mConn->lowlevel()->maxPresenceStatusMessageLength(), (uint) 512);
234 }
235
cleanup()236 void TestConnBasics::cleanup()
237 {
238 if (mConn) {
239 QVERIFY(mConn->isValid());
240
241 GHashTable *details = tp_asv_new(
242 "debug-message", G_TYPE_STRING, "woo i'm going doooooown",
243 "x-tpqt-test-rgba-herring-color", G_TYPE_UINT, 0xff0000ffU,
244 NULL
245 );
246
247 // Disconnect and wait for invalidation
248 tp_base_connection_disconnect_with_dbus_error(TP_BASE_CONNECTION(mConnService),
249 TP_QT_ERROR_CANCELLED.latin1(),
250 details,
251 TP_CONNECTION_STATUS_REASON_REQUESTED);
252
253 g_hash_table_destroy(details);
254
255 QVERIFY(connect(mConn.data(),
256 SIGNAL(invalidated(Tp::DBusProxy *,
257 const QString &, const QString &)),
258 SLOT(expectConnInvalidated())));
259 QCOMPARE(mLoop->exec(), 0);
260 QVERIFY(!mConn->isValid());
261
262 // Check that we got the connection error details
263 QCOMPARE(static_cast<uint>(mConn->statusReason()),
264 static_cast<uint>(ConnectionStatusReasonRequested));
265
266 QVERIFY(mConn->errorDetails().isValid());
267
268 QVERIFY(mConn->errorDetails().hasDebugMessage());
269 QCOMPARE(mConn->errorDetails().debugMessage(), QLatin1String("woo i'm going doooooown"));
270
271 #if 0
272 // Not yet there
273 QVERIFY(!mConn->errorDetails().hasExpectedHostname());
274 QVERIFY(!mConn->errorDetails().hasCertificateHostname());
275 #endif
276
277 QVERIFY(mConn->errorDetails().allDetails().contains(
278 QLatin1String("x-tpqt-test-rgba-herring-color")));
279 QCOMPARE(qdbus_cast<uint>(mConn->errorDetails().allDetails().value(
280 QLatin1String("x-tpqt-test-rgba-herring-color"))),
281 0xff0000ffU);
282
283 processDBusQueue(mConn.data());
284
285 mConn.reset();
286 }
287
288 if (mConnService != 0) {
289 g_object_unref(mConnService);
290 mConnService = 0;
291 }
292
293 cleanupImpl();
294 }
295
cleanupTestCase()296 void TestConnBasics::cleanupTestCase()
297 {
298 cleanupTestCaseImpl();
299 }
300
301 QTEST_MAIN(TestConnBasics)
302 #include "_gen/conn-basics.cpp.moc.hpp"
303