1 #include <tests/lib/test.h>
2 
3 #include <tests/lib/glib-helpers/test-conn-helper.h>
4 
5 #include <tests/lib/glib/simple-conn.h>
6 #include <tests/lib/glib/captcha-chan.h>
7 
8 #include <TelepathyQt/Captcha>
9 #include <TelepathyQt/CaptchaAuthentication>
10 #include <TelepathyQt/Connection>
11 #include <TelepathyQt/PendingReady>
12 #include <TelepathyQt/PendingCaptchas>
13 #include <TelepathyQt/ReferencedHandles>
14 #include <TelepathyQt/ServerAuthenticationChannel>
15 
16 #include <telepathy-glib/telepathy-glib.h>
17 
18 #include <stdio.h>
19 
20 using namespace Tp;
21 
22 class TestCaptchaAuthentication : public Test
23 {
24     Q_OBJECT
25 
26 public:
TestCaptchaAuthentication(QObject * parent=0)27     TestCaptchaAuthentication(QObject *parent = 0)
28         : Test(parent),
29           mConn(0), mChanService(0)
30     { }
31 
32 private Q_SLOTS:
33     void initTestCase();
34     void init();
35 
36     void testCreation();
37     void testCaptchaSuccessful();
38     void testCaptchaRetry();
39     void testCaptchaCancel();
40     void testNoCaptcha();
41 
42     void cleanup();
43     void cleanupTestCase();
44 
45 private:
46     void createCaptchaChannel(bool canRetry = false);
47 
48     TestConnHelper *mConn;
49     TpTestsCaptchaChannel *mChanService;
50     ServerAuthenticationChannelPtr mChan;
51     CaptchaAuthenticationPtr mCaptcha;
52 };
53 
createCaptchaChannel(bool canRetry)54 void TestCaptchaAuthentication::createCaptchaChannel(bool canRetry)
55 {
56     mChan.reset();
57     mLoop->processEvents();
58     tp_clear_object(&mChanService);
59 
60     /* Create service-side tube channel object */
61     QString chanPath = QString(QLatin1String("%1/Channel")).arg(mConn->objectPath());
62 
63     mChanService = TP_TESTS_CAPTCHA_CHANNEL(g_object_new(
64             TP_TESTS_TYPE_CAPTCHA_CHANNEL,
65             "connection", mConn->service(),
66             "requested", FALSE,
67             "object-path", chanPath.toLatin1().constData(),
68             "can-retry-captcha", canRetry,
69             NULL));
70 
71     /* Create client-side tube channel object */
72     mChan = ServerAuthenticationChannel::create(mConn->client(), chanPath, QVariantMap());
73 
74     // Verify features shouldn't be Ready
75     QVERIFY(mChan->captchaAuthentication().isNull());
76     QVERIFY(!mChan->hasCaptchaInterface());
77     //QVERIFY(!mChan->hasSaslInterface());
78 
79     QVERIFY(connect(mChan->becomeReady(ServerAuthenticationChannel::FeatureCore),
80                 SIGNAL(finished(Tp::PendingOperation *)),
81                 SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
82     QCOMPARE(mLoop->exec(), 0);
83 
84     QVERIFY(mChan->isReady(ServerAuthenticationChannel::FeatureCore));
85     QVERIFY(mChan->hasCaptchaInterface());
86     //QVERIFY(!mChan->hasSaslInterface());
87 
88     mCaptcha = mChan->captchaAuthentication();
89 
90     QCOMPARE(mCaptcha.isNull(), false);
91 }
92 
initTestCase()93 void TestCaptchaAuthentication::initTestCase()
94 {
95     initTestCaseImpl();
96 
97     g_type_init();
98     g_set_prgname("captcha-authentication");
99     tp_debug_set_flags("all");
100     dbus_g_bus_get(DBUS_BUS_STARTER, 0);
101 
102     mConn = new TestConnHelper(this,
103             TP_TESTS_TYPE_SIMPLE_CONNECTION,
104             "account", "me@example.com",
105             "protocol", "example",
106             NULL);
107     QCOMPARE(mConn->connect(), true);
108 }
109 
init()110 void TestCaptchaAuthentication::init()
111 {
112     initImpl();
113 }
114 
testCreation()115 void TestCaptchaAuthentication::testCreation()
116 {
117     createCaptchaChannel();
118 
119     QCOMPARE(mCaptcha->status(), Tp::CaptchaStatusLocalPending);
120     QCOMPARE(mCaptcha->canRetry(), false);
121     QVERIFY(mCaptcha->error().isEmpty());
122     QVERIFY(mCaptcha->errorDetails().allDetails().isEmpty());
123 }
124 
testCaptchaSuccessful()125 void TestCaptchaAuthentication::testCaptchaSuccessful()
126 {
127     createCaptchaChannel();
128 
129     QSignalSpy spy(mCaptcha.data(), SIGNAL(statusChanged(Tp::CaptchaStatus)));
130 
131     PendingCaptchas *pendingCaptchas = mCaptcha->requestCaptchas(QStringList() << QLatin1String("image/png"));
132     QVERIFY(connect(pendingCaptchas,
133                 SIGNAL(finished(Tp::PendingOperation *)),
134                 SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
135     QCOMPARE(mLoop->exec(), 0);
136 
137     QCOMPARE(pendingCaptchas->requiresMultipleCaptchas(), false);
138     QCOMPARE(pendingCaptchas->captchaList().size(), 1);
139 
140     Captcha captchaData = pendingCaptchas->captcha();
141 
142     QCOMPARE(captchaData.mimeType(), QLatin1String("image/png"));
143     QCOMPARE(captchaData.label(), QLatin1String("Enter the text displayed"));
144     QCOMPARE(captchaData.data(), QByteArray("This is a fake payload"));
145     QCOMPARE(captchaData.type(), CaptchaAuthentication::OCRChallenge);
146     QCOMPARE(captchaData.id(), (uint)42);
147 
148     QVERIFY(connect(mCaptcha->answer(42, QLatin1String("This is the right answer")),
149                 SIGNAL(finished(Tp::PendingOperation *)),
150                 SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
151     QCOMPARE(mLoop->exec(), 0);
152 
153     QCOMPARE(spy.size(), 2);
154     QCOMPARE(mCaptcha->status(), CaptchaStatusSucceeded);
155 }
156 
testCaptchaRetry()157 void TestCaptchaAuthentication::testCaptchaRetry()
158 {
159     createCaptchaChannel(true);
160     QSignalSpy spy(mCaptcha.data(), SIGNAL(statusChanged(Tp::CaptchaStatus)));
161 
162     PendingCaptchas *pendingCaptchas = mCaptcha->requestCaptchas(QStringList() << QLatin1String("image/png"));
163     QVERIFY(connect(pendingCaptchas,
164                 SIGNAL(finished(Tp::PendingOperation *)),
165                 SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
166     QCOMPARE(mLoop->exec(), 0);
167 
168     QVERIFY(connect(mCaptcha->answer(42, QLatin1String("What is this I don't even")),
169                 SIGNAL(finished(Tp::PendingOperation *)),
170                 SLOT(expectFailure(Tp::PendingOperation *))));
171     QCOMPARE(mLoop->exec(), 0);
172 
173     QCOMPARE(mCaptcha->status(), CaptchaStatusTryAgain);
174 
175     pendingCaptchas = mCaptcha->requestCaptchas(QStringList() << QLatin1String("image/png"));
176     QVERIFY(connect(pendingCaptchas,
177                 SIGNAL(finished(Tp::PendingOperation *)),
178                 SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
179     QCOMPARE(mLoop->exec(), 0);
180 
181     QCOMPARE(pendingCaptchas->requiresMultipleCaptchas(), false);
182     QCOMPARE(pendingCaptchas->captchaList().size(), 1);
183 
184     Captcha captchaData = pendingCaptchas->captcha();
185 
186     QCOMPARE(captchaData.mimeType(), QLatin1String("image/png"));
187     QCOMPARE(captchaData.label(), QLatin1String("Enter the text displayed"));
188     QCOMPARE(captchaData.data(), QByteArray("This is a reloaded payload"));
189     QCOMPARE(captchaData.type(), CaptchaAuthentication::OCRChallenge);
190     QCOMPARE(captchaData.id(), (uint)42);
191 
192     QVERIFY(connect(mCaptcha->answer(42, QLatin1String("This is the right answer")),
193                 SIGNAL(finished(Tp::PendingOperation *)),
194                 SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
195     QCOMPARE(mLoop->exec(), 0);
196 
197     QCOMPARE(mCaptcha->status(), CaptchaStatusSucceeded);
198 
199     // Check signals now
200     QCOMPARE(spy.size(), 5);
201 }
202 
testCaptchaCancel()203 void TestCaptchaAuthentication::testCaptchaCancel()
204 {
205     createCaptchaChannel();
206 
207     PendingCaptchas *pendingCaptchas = mCaptcha->requestCaptchas(QStringList() << QLatin1String("image/png"));
208     QVERIFY(connect(pendingCaptchas,
209                 SIGNAL(finished(Tp::PendingOperation *)),
210                 SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
211     // Check that the result is not still available
212     QCOMPARE(pendingCaptchas->captchaList().size(), 0);
213     QCOMPARE(pendingCaptchas->captcha().id(), (uint)0);
214     QCOMPARE(mLoop->exec(), 0);
215 
216     // Cancel now
217     QVERIFY(connect(mCaptcha->cancel(CaptchaCancelReasonUserCancelled),
218                 SIGNAL(finished(Tp::PendingOperation *)),
219                 SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
220     QCOMPARE(mLoop->exec(), 0);
221 
222     QCOMPARE(mCaptcha->status(), CaptchaStatusFailed);
223 
224     // Now try performing random actions which should fail
225     QVERIFY(connect(mCaptcha->answer(42, QLatin1String("This is the right answer")),
226                 SIGNAL(finished(Tp::PendingOperation *)),
227                 SLOT(expectFailure(Tp::PendingOperation *))));
228     QCOMPARE(mLoop->exec(), 0);
229 
230     QVERIFY(connect(mCaptcha->answer(CaptchaAnswers()),
231                 SIGNAL(finished(Tp::PendingOperation *)),
232                 SLOT(expectFailure(Tp::PendingOperation *))));
233     QCOMPARE(mLoop->exec(), 0);
234 
235     QVERIFY(connect(mCaptcha->requestCaptchas(),
236                 SIGNAL(finished(Tp::PendingOperation *)),
237                 SLOT(expectFailure(Tp::PendingOperation *))));
238     QCOMPARE(mLoop->exec(), 0);
239 }
240 
testNoCaptcha()241 void TestCaptchaAuthentication::testNoCaptcha()
242 {
243     createCaptchaChannel();
244 
245     PendingCaptchas *pendingCaptchas = mCaptcha->requestCaptchas(QStringList(), CaptchaAuthentication::AudioRecognitionChallenge);
246     QVERIFY(connect(pendingCaptchas,
247                 SIGNAL(finished(Tp::PendingOperation *)),
248                 SLOT(expectFailure(Tp::PendingOperation *))));
249     QCOMPARE(mLoop->exec(), 0);
250 
251     pendingCaptchas = mCaptcha->requestCaptchas(QStringList() << QLatin1String("nosuchtype"),
252         CaptchaAuthentication::SpeechRecognitionChallenge | CaptchaAuthentication::SpeechQuestionChallenge);
253     QVERIFY(connect(pendingCaptchas,
254                 SIGNAL(finished(Tp::PendingOperation *)),
255                 SLOT(expectFailure(Tp::PendingOperation *))));
256     QCOMPARE(mLoop->exec(), 0);
257 
258     // Get the qa one
259     pendingCaptchas = mCaptcha->requestCaptchas(QStringList(), CaptchaAuthentication::TextQuestionChallenge);
260     QVERIFY(connect(pendingCaptchas,
261                 SIGNAL(finished(Tp::PendingOperation *)),
262                 SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
263     QCOMPARE(mLoop->exec(), 0);
264 
265     Captcha data = pendingCaptchas->captcha();
266     Captcha data2(pendingCaptchas->captcha());
267 
268     QCOMPARE(data.id(), pendingCaptchas->captcha().id());
269     QCOMPARE(data.id(), data2.id());
270 
271     // Get the video one to fail utterly
272     pendingCaptchas = mCaptcha->requestCaptchas(QStringList(), CaptchaAuthentication::VideoRecognitionChallenge);
273     QVERIFY(connect(pendingCaptchas,
274                 SIGNAL(finished(Tp::PendingOperation *)),
275                 SLOT(expectFailure(Tp::PendingOperation *))));
276     QCOMPARE(mLoop->exec(), 0);
277 }
278 
cleanup()279 void TestCaptchaAuthentication::cleanup()
280 {
281     cleanupImpl();
282 
283     if (mChan && mChan->isValid()) {
284         qDebug() << "waiting for the channel to become invalidated";
285 
286         QVERIFY(connect(mChan.data(),
287                 SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
288                 mLoop,
289                 SLOT(quit())));
290         tp_base_channel_close(TP_BASE_CHANNEL(mChanService));
291         QCOMPARE(mLoop->exec(), 0);
292     }
293 
294     mChan.reset();
295 
296     if (mChanService != 0) {
297         g_object_unref(mChanService);
298         mChanService = 0;
299     }
300 
301     mLoop->processEvents();
302 }
303 
cleanupTestCase()304 void TestCaptchaAuthentication::cleanupTestCase()
305 {
306     QCOMPARE(mConn->disconnect(), true);
307     delete mConn;
308 
309     cleanupTestCaseImpl();
310 }
311 
312 QTEST_MAIN(TestCaptchaAuthentication)
313 #include "_gen/captcha-authentication.cpp.moc.hpp"
314