1 /*
2  * This file is part of signon
3  *
4  * Copyright (C) 2009-2010 Nokia Corporation.
5  * Copyright (C) 2013-2016 Canonical Ltd.
6  *
7  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * version 2.1 as published by the Free Software Foundation.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23 
24 #include "signon-ui.h"
25 #include "testauthsession.h"
26 #include "testthread.h"
27 #include "SignOn/identity.h"
28 #include <QDBusInterface>
29 #include <sys/wait.h>
30 #include <unistd.h>
31 
32 #define SSO_TEST_CREATE_AUTH_SESSION(__session__, __method__) \
33     do {                                                            \
34         Identity *id = Identity::newIdentity(IdentityInfo(), this); \
35         __session__ = id->createSession(QLatin1String(__method__)); \
36     } while(0)
37 
38 
39 static AuthSession *g_currentSession = NULL;
40 static QStringList g_processReplyRealmsList;
41 static int g_bigStringSize = 50000;
42 static int g_bigStringReplySize = 0;
43 
TestAuthSession(SignOnUI * signOnUI,QObject * parent)44 TestAuthSession::TestAuthSession(SignOnUI *signOnUI, QObject *parent):
45     QObject(parent),
46     m_signOnUI(signOnUI)
47 {
48 }
49 
initTestCase()50 void TestAuthSession::initTestCase()
51 {
52     qDebug() << "HI!";
53 }
54 
cleanupTestCase()55 void TestAuthSession::cleanupTestCase()
56 {
57     qDebug() << "BYE!";
58 }
59 
sessionData()60 void TestAuthSession::sessionData()
61 {
62     QVariantMap originalMap;
63     originalMap["Hello"] = "World";
64     originalMap["Int"] = 4;
65 
66     SessionData sessionData(originalMap);
67     QCOMPARE(sessionData.toMap(), originalMap);
68 }
69 
queryMechanisms_existing_method()70 void TestAuthSession::queryMechanisms_existing_method()
71 {
72     AuthSession *as;
73     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
74 
75     QStringList wantedMechs;
76 
77     QSignalSpy spy(as, SIGNAL(mechanismsAvailable(const QStringList&)));
78     QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &)));
79     QEventLoop loop;
80 
81     QObject::connect(as, SIGNAL(mechanismsAvailable(const QStringList&)),
82                      &loop, SLOT(quit()));
83     QObject::connect(as, SIGNAL(error(const SignOn::Error &)),
84                      &loop, SLOT(quit()));
85     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
86 
87     as->queryAvailableMechanisms(wantedMechs);
88 
89     if (!errorCounter.count())
90         loop.exec();
91 
92     errorCounter.clear();
93 
94     QCOMPARE(spy.count(), 1);
95     QStringList result = spy.at(0).at(0).toStringList();
96     QCOMPARE(result.size(), 4);
97 
98     wantedMechs += "mech1";
99 
100     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
101 
102     as->queryAvailableMechanisms(wantedMechs);
103 
104     if (!errorCounter.count())
105         loop.exec();
106 
107     errorCounter.clear();
108 
109     QCOMPARE(spy.count(), 2);
110     result = spy.at(1).at(0).toStringList();
111     QCOMPARE(result.size(), 1);
112 
113     wantedMechs += "mech2";
114 
115     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
116 
117     as->queryAvailableMechanisms(wantedMechs);
118 
119     if (!errorCounter.count())
120         loop.exec();
121 
122     errorCounter.clear();
123 
124     QCOMPARE(spy.count(), 3);
125     result = spy.at(2).at(0).toStringList();
126     QCOMPARE(result.size(), 2);
127 
128     wantedMechs = QStringList("fake");
129 
130     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
131 
132     as->queryAvailableMechanisms(wantedMechs);
133 
134     if (!errorCounter.count())
135         loop.exec();
136 
137     errorCounter.clear();
138 
139     QCOMPARE(spy.count(), 4);
140     result = spy.at(3).at(0).toStringList();
141     QCOMPARE(result.size(), 0);
142  }
143 
queryMechanisms_nonexisting_method()144  void TestAuthSession::queryMechanisms_nonexisting_method()
145  {
146      AuthSession *as;
147      SSO_TEST_CREATE_AUTH_SESSION(as, "nonexisting");
148 
149      QStringList wantedMechs;
150 
151      QSignalSpy spy(as, SIGNAL(error(const SignOn::Error &)));
152      QEventLoop loop;
153 
154      QObject::connect(as, SIGNAL(mechanismsAvailable(const QStringList&)), &loop, SLOT(quit()));
155      QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()));
156      QTimer::singleShot(10*1000, &loop, SLOT(quit()));
157 
158      as->queryAvailableMechanisms(wantedMechs);
159      loop.exec();
160 
161      QCOMPARE(spy.count(), 1);
162  }
163 
process_with_new_identity()164  void TestAuthSession::process_with_new_identity()
165  {
166      AuthSession *as;
167      SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
168 
169      g_processReplyRealmsList.clear();
170      connect(as, SIGNAL(response(const SignOn::SessionData &)), this, SLOT(response(const SignOn::SessionData &)));
171 
172      QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData &)));
173      QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &)));
174      QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&)));
175      QEventLoop loop;
176 
177      QObject::connect(as, SIGNAL(response(const SignOn::SessionData &)), &loop, SLOT(quit()), Qt::QueuedConnection);
178      QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()));
179      QTimer::singleShot(10*1000, &loop, SLOT(quit()));
180 
181      SessionData inData;
182 
183      inData.setSecret("testSecret");
184      inData.setUserName("testUsername");
185 
186      as->process(inData, "mech1");
187      if (!errorCounter.count())
188          loop.exec();
189 
190      QCOMPARE(stateCounter.count(), 12);
191      stateCounter.clear();
192      errorCounter.clear();
193 
194      as->process(inData, "mech1");
195      if (!errorCounter.count())
196          loop.exec();
197 
198      QCOMPARE(stateCounter.count(), 12);
199      stateCounter.clear();
200      errorCounter.clear();
201 
202      as->process(inData, "mech1");
203      if (!errorCounter.count())
204          loop.exec();
205 
206      QCOMPARE(stateCounter.count(), 12);
207      stateCounter.clear();
208      errorCounter.clear();
209 
210      as->process(inData, "mech1");
211      if (!errorCounter.count())
212          loop.exec();
213 
214      QCOMPARE(stateCounter.count(), 12);
215      stateCounter.clear();
216      errorCounter.clear();
217 
218      QCOMPARE(spy.count(), 4);
219 
220      QVERIFY(g_processReplyRealmsList.at(0) == "testRealm_after_test");
221      QVERIFY(g_processReplyRealmsList.at(1) == "testRealm_after_test");
222      QVERIFY(g_processReplyRealmsList.at(2) == "testRealm_after_test");
223      QVERIFY(g_processReplyRealmsList.at(3) == "testRealm_after_test");
224  }
225 
process_with_existing_identity()226  void TestAuthSession::process_with_existing_identity()
227  {
228      AuthSession *as;
229      SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
230 
231      g_processReplyRealmsList.clear();
232      connect(as, SIGNAL(response(const SignOn::SessionData &)), this, SLOT(response(const SignOn::SessionData &)));
233 
234      QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &)));
235      QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&)));
236      QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData&)));
237      QEventLoop loop;
238 
239      QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit()));
240      QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()));
241      QTimer::singleShot(10*1000, &loop, SLOT(quit()));
242 
243      SessionData inData;
244 
245      inData.setSecret("testSecret");
246      inData.setUserName("testUsername");
247 
248      as->process(inData, "mech1");
249      if (!errorCounter.count())
250          loop.exec();
251      QCOMPARE(stateCounter.count(), 12);
252      stateCounter.clear();
253      errorCounter.clear();
254 
255      as->process(inData, "mech1");
256      if (!errorCounter.count())
257          loop.exec();
258      QCOMPARE(stateCounter.count(), 12);
259      stateCounter.clear();
260      errorCounter.clear();
261 
262      as->process(inData, "mech1");
263      if (!errorCounter.count())
264          loop.exec();
265      QCOMPARE(stateCounter.count(), 12);
266      stateCounter.clear();
267      errorCounter.clear();
268 
269      as->process(inData, "mech1");
270      if (!errorCounter.count())
271          loop.exec();
272      QCOMPARE(stateCounter.count(), 12);
273      stateCounter.clear();
274      errorCounter.clear();
275 
276      QCOMPARE(spy.count(), 4);
277 
278      QVERIFY(g_processReplyRealmsList.at(0) == "testRealm_after_test");
279      QVERIFY(g_processReplyRealmsList.at(1) == "testRealm_after_test");
280      QVERIFY(g_processReplyRealmsList.at(2) == "testRealm_after_test");
281      QVERIFY(g_processReplyRealmsList.at(3) == "testRealm_after_test");
282 
283  }
284 
process_with_nonexisting_type()285  void TestAuthSession::process_with_nonexisting_type()
286  {
287      AuthSession *as;
288      SSO_TEST_CREATE_AUTH_SESSION(as, "nonexisting");
289 
290      QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData &)));
291      QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
292      QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&)));
293      QEventLoop loop;
294 
295      QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()),  Qt::QueuedConnection);
296      QTimer::singleShot(10*1000, &loop, SLOT(quit()));
297 
298      SessionData inData;
299 
300      inData.setSecret("testSecret");
301      inData.setUserName("testUsername");
302 
303      as->process(inData, "mech1");
304      loop.exec();
305 
306      as->process(inData, "mech1");
307      loop.exec();
308 
309      as->process(inData, "mech1");
310      loop.exec();
311 
312      as->process(inData, "mech1");
313      loop.exec();
314 
315      QCOMPARE(spyResponse.count(), 0);
316      QCOMPARE(spyError.count(), 4);
317      QVERIFY(stateCounter.count() <= 4);
318  }
319 
320 
process_with_nonexisting_method()321  void TestAuthSession::process_with_nonexisting_method()
322  {
323      AuthSession *as;
324      SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
325 
326      QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&)));
327      QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
328      QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&)));
329      QEventLoop loop;
330 
331      QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()),  Qt::QueuedConnection);
332      QTimer::singleShot(10*1000, &loop, SLOT(quit()));
333 
334      SessionData inData;
335 
336      inData.setSecret("testSecret");
337      inData.setUserName("testUsername");
338 
339      as->process(inData, "nonexisting");
340      loop.exec();
341 
342      as->process(inData, "nonexisting");
343      loop.exec();
344 
345      as->process(inData, "nonexisting");
346      loop.exec();
347 
348      as->process(inData, "nonexisting");
349      loop.exec();
350 
351      QCOMPARE(spyResponse.count(), 0);
352      QCOMPARE(spyError.count(), 4);
353      QCOMPARE(stateCounter.count(), 8);
354  }
355 
process_with_unauthorized_method()356 void TestAuthSession::process_with_unauthorized_method()
357 {
358     MechanismsList mechs;
359     mechs.append("mech1");
360     QMap<MethodName,MechanismsList> methods;
361     methods.insert(QLatin1String("ssotest"), mechs);
362     IdentityInfo info("test_caption", "test_user_name", methods);
363     info.setSecret("test_secret");
364     info.setAccessControlList(QStringList() << "*");
365     Identity *id = Identity::newIdentity(info, this);
366 
367     QSignalSpy spyResponseStoreCreds(id, SIGNAL(credentialsStored(const quint32)));
368     QSignalSpy spyErrorStoreCreds(id, SIGNAL(error(const SignOn::Error &)));
369 
370     QEventLoop loopStoreCreds;
371 
372     QObject::connect(id, SIGNAL(error(const SignOn::Error &)), &loopStoreCreds, SLOT(quit()),  Qt::QueuedConnection);
373     QObject::connect(id, SIGNAL(credentialsStored(const quint32)), &loopStoreCreds, SLOT(quit()));
374     QTimer::singleShot(10*1000, &loopStoreCreds, SLOT(quit()));
375 
376     id->storeCredentials();
377     loopStoreCreds.exec();
378 
379     QCOMPARE(spyResponseStoreCreds.count(), 1);
380     QCOMPARE(spyErrorStoreCreds.count(), 0);
381 
382     AuthSession *as = id->createSession(QLatin1String("ssotest"));
383 
384     QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData &)));
385     QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
386     QEventLoop loop;
387 
388     QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()),  Qt::QueuedConnection);
389     QObject::connect(as, SIGNAL(response(const SignOn::SessionData &)), &loop, SLOT(quit()));
390     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
391 
392     SessionData inData;
393     as->process(inData, "mech2");
394     loop.exec();
395 
396     QCOMPARE(spyResponse.count(), 0);
397     QCOMPARE(spyError.count(), 1);
398     // Still make sure the error really was about bad auth method/mechanism
399     SignOn::Error::ErrorType errorType = SignOn::Error::Unknown;
400     QVariant var = spyError.at(0).at(0);
401     if (QLatin1String("SignOn::Error") == var.typeName()) {
402        SignOn::Error error = var.value<SignOn::Error>();
403        errorType = (SignOn::Error::ErrorType)error.type();
404     }
405     QCOMPARE(errorType, SignOn::Error::MethodOrMechanismNotAllowed);
406 }
407 
process_many_times_after_auth()408 void TestAuthSession::process_many_times_after_auth()
409 {
410     AuthSession *as;
411     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
412 
413     QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&)));
414     QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
415     QEventLoop loop;
416 
417     QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()));
418     QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit()));
419     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
420 
421     SessionData inData;
422 
423     inData.setSecret("testSecret");
424     inData.setUserName("testUsername");
425 
426     as->process(inData, "mech1");
427     loop.exec();
428     QCOMPARE(spyResponse.count(), 1);
429 
430     as->process(inData, "mech1");
431     as->process(inData, "mech1");
432     as->process(inData, "mech1");
433     as->process(inData, "mech1");
434 
435     loop.exec();
436 
437     QCOMPARE(spyResponse.count(), 2);
438     QCOMPARE(spyError.count(), 3);
439 
440     as->process(inData, "mech1");
441     as->process(inData, "mech1");
442     as->process(inData, "mech1");
443     as->process(inData, "mech1");
444 
445     loop.exec();
446 
447     QCOMPARE(spyResponse.count(), 3);
448     QCOMPARE(spyError.count(), 6);
449 
450     as->process(inData, "mech1");
451     as->process(inData, "mech1");
452     as->process(inData, "mech1");
453     as->process(inData, "mech1");
454 
455     loop.exec();
456 
457     QCOMPARE(spyResponse.count(), 4);
458     QCOMPARE(spyError.count(), 9);
459 }
460 
process_many_times_before_auth()461 void TestAuthSession::process_many_times_before_auth()
462 {
463     AuthSession *as;
464     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
465 
466     QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&)));
467     QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
468     QEventLoop loop;
469 
470     QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)),
471                      &loop, SLOT(quit()));
472     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
473 
474     SessionData inData;
475 
476     inData.setSecret("testSecret");
477     inData.setUserName("testUsername");
478 
479     as->process(inData, "mech1");
480     as->process(inData, "mech1");
481     as->process(inData, "mech1");
482     as->process(inData, "mech1");
483 
484     loop.exec();
485 
486     QCOMPARE(spyError.count(), 3);
487     QCOMPARE(spyResponse.count(), 1);
488 }
489 
process_with_big_session_data()490 void TestAuthSession::process_with_big_session_data()
491 {
492     //TODO once bug Bug#222200 is fixed, this test case can be enabled
493     QSKIP("This test requires fix", SkipSingle);
494     AuthSession *as;
495     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
496 
497     QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&)));
498     QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
499     QEventLoop loop;
500 
501     QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)),
502                      this, SLOT(response(const SignOn::SessionData&)));
503     QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)),
504                      &loop, SLOT(quit()));
505     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
506 
507     SessionData inData;
508 
509     inData.setSecret("testSecret");
510 
511     QString bigString;
512     bigString.fill(QChar('A'), g_bigStringSize);
513     inData.setCaption(bigString);
514 
515     as->process(inData, "BLOB");
516 
517     loop.exec();
518 
519     QCOMPARE(spyError.count(), 0);
520     QCOMPARE(spyResponse.count(), 1);
521     QCOMPARE(g_bigStringReplySize, g_bigStringSize);
522 }
523 
process_after_timeout()524 void TestAuthSession::process_after_timeout()
525 {
526     AuthSession *as;
527     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
528 
529     QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&)));
530     QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
531     QEventLoop loop;
532 
533     QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)),
534                      &loop, SLOT(quit()));
535     QTimer::singleShot(20*1000, &loop, SLOT(quit()));
536 
537     SessionData inData;
538 
539     inData.setSecret("testSecret");
540     inData.setUserName("testUsername");
541 
542     as->process(inData, "mech1");
543 
544     loop.exec();
545 
546     QCOMPARE(spyResponse.count(), 1);
547     QCOMPARE(spyError.count(), 0);
548     spyResponse.clear();
549 
550     // Wait for auto-destruction of the remote object
551     QTest::qWait(6000);
552 
553     /* Create an authsession just to trigger the actual destruction of the
554      * first. */
555     AuthSession *as2;
556     SSO_TEST_CREATE_AUTH_SESSION(as2, "ssotest");
557     Q_UNUSED(as2);
558 
559     // Try processing again
560     as->process(inData, "mech1");
561 
562     loop.exec();
563 
564     QCOMPARE(spyResponse.count(), 1);
565     QCOMPARE(spyError.count(), 0);
566 }
567 
cancel_immediately()568 void TestAuthSession::cancel_immediately()
569 {
570     AuthSession *as;
571     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
572 
573     QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&)));
574     QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
575     QEventLoop loop;
576 
577     QObject::connect(as, SIGNAL(error(const SignOn::Error &)),
578                      &loop, SLOT(quit()));
579     QObject::connect(as, SIGNAL(error(const SignOn::Error &)),
580                      &loop, SLOT(quit()),  Qt::QueuedConnection);
581     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
582 
583     SessionData inData;
584 
585     inData.setSecret("testSecret");
586     inData.setUserName("testUsername");
587 
588     as->process(inData, "mech1");
589     as->cancel();
590     loop.exec();
591 
592     QCOMPARE(spyResponse.count(), 0);
593     QCOMPARE(spyError.count(), 1);
594 
595     as->process(inData, "mech1");
596     as->cancel();
597     loop.exec();
598 
599     QCOMPARE(spyResponse.count(), 0);
600     QCOMPARE(spyError.count(), 2);
601 
602     as->process(inData, "mech1");
603     as->cancel();
604     loop.exec();
605 
606     QCOMPARE(spyResponse.count(), 0);
607     QCOMPARE(spyError.count(), 3);
608 
609     as->process(inData, "mech1");
610     as->cancel();
611     loop.exec();
612 
613     QCOMPARE(spyResponse.count(), 0);
614     QCOMPARE(spyError.count(), 4);
615 }
616 
cancel_with_delay()617 void TestAuthSession::cancel_with_delay()
618 {
619     AuthSession *as;
620     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
621     g_currentSession = as;
622 
623     QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&)));
624     QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
625     QEventLoop loop;
626 
627     QObject::connect(as, SIGNAL(error(const SignOn::Error &)),
628                      &loop, SLOT(quit()));
629     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
630 
631     SessionData inData;
632 
633     inData.setSecret("testSecret");
634     inData.setUserName("testUsername");
635 
636     as->process(inData, "mech1");
637     QTimer::singleShot(0.1*1000, this, SLOT(cancel()));
638     loop.exec();
639 
640     QCOMPARE(spyResponse.count(), 0);
641     QCOMPARE(spyError.count(), 1);
642 
643     as->process(inData, "mech1");
644     QTimer::singleShot(0.1*1000, this, SLOT(cancel()));
645     loop.exec();
646 
647     QCOMPARE(spyResponse.count(), 0);
648     QCOMPARE(spyError.count(), 2);
649 
650     as->process(inData, "mech1");
651     QTimer::singleShot(0.1*1000, this, SLOT(cancel()));
652     loop.exec();
653 
654     QCOMPARE(spyResponse.count(), 0);
655     QCOMPARE(spyError.count(), 3);
656 
657     as->process(inData, "mech1");
658     QTimer::singleShot(0.1*1000, this, SLOT(cancel()));
659     loop.exec();
660 
661     QCOMPARE(spyResponse.count(), 0);
662     QCOMPARE(spyError.count(), 4);
663 }
664 
cancel_without_process()665 void TestAuthSession::cancel_without_process()
666 {
667     AuthSession *as;
668     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
669     g_currentSession = as;
670 
671     QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &)));
672     QEventLoop loop;
673 
674     QObject::connect(as, SIGNAL(error(const SignOn::Error &)),
675                      &loop, SLOT(quit()),  Qt::QueuedConnection);
676     QTimer::singleShot(10*1000, &loop, SLOT(quit()));
677 
678     QTimer::singleShot(1*1000, &loop, SLOT(quit()));
679     as->cancel();
680     loop.exec();
681 
682     QCOMPARE(spyError.count(), 0);
683 
684     QTimer::singleShot(1*1000, &loop, SLOT(quit()));
685     QTimer::singleShot(0.1*1000, this, SLOT(cancel()));
686     loop.exec();
687 
688     QCOMPARE(spyError.count(), 0);
689 
690     QTimer::singleShot(0.1*1000, this, SLOT(cancel()));
691     QTimer::singleShot(1*1000, &loop, SLOT(quit()));
692     loop.exec();
693 
694     QCOMPARE(spyError.count(), 0);
695 
696     SessionData inData;
697 
698     inData.setSecret("testSecret");
699     inData.setUserName("testUsername");
700 
701     as->process(inData, "mech1");
702     as->cancel();
703     as->cancel();
704     as->cancel();
705     loop.exec();
706 
707     QCOMPARE(spyError.count(), 1);
708 }
709 
handle_destroyed_signal()710 void TestAuthSession::handle_destroyed_signal()
711 {
712     QSKIP("testing in sb", SkipSingle);
713     AuthSession *as;
714     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest");
715     g_currentSession = as;
716 
717     QSignalSpy spy(as, SIGNAL(mechanismsAvailable(const QStringList&)));
718     QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &)));
719     QEventLoop loop;
720 
721     QObject::connect(as, SIGNAL(mechanismsAvailable(const QStringList&)),
722                      &loop, SLOT(quit()));
723     QObject::connect(as, SIGNAL(error(const SignOn::Error &)),
724                      &loop, SLOT(quit()));
725 
726     /*
727      * 5 minutes + 10 seconds
728      * */
729     QTimer::singleShot(5 * 62 *1000, &loop, SLOT(quit()));
730     loop.exec();
731 
732     QTimer::singleShot(5 * 1000, &loop, SLOT(quit()));
733     loop.exec();
734 
735     QStringList wantedMechs;
736     as->queryAvailableMechanisms(wantedMechs);
737 
738     if (!errorCounter.count())
739         loop.exec();
740 
741     QCOMPARE(spy.count(), 1);
742     QStringList result = spy.at(0).at(0).toStringList();
743     QCOMPARE(result.size(), 4);
744 }
745 
multi_thread_test()746 void TestAuthSession::multi_thread_test()
747 {
748     //execute a SignOn call in a separate thread
749     TestThread thread;
750     thread.start();
751     thread.wait(g_testThreadTimeout + 1000);
752 
753     //do the same in this thread - this test succeeds if the
754     //following succeeds
755     process_with_new_identity();
756 }
757 
cancel()758 void TestAuthSession::cancel()
759 {
760     g_currentSession->cancel();
761 }
762 
response(const SignOn::SessionData & data)763 void TestAuthSession::response(const SignOn::SessionData &data)
764 {
765     g_processReplyRealmsList << data.Realm();
766     g_bigStringReplySize = data.Caption().size();
767 }
768 
processUi_with_existing_identity()769 void TestAuthSession::processUi_with_existing_identity()
770 {
771     AuthSession *as;
772     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest2");
773 
774     QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &)));
775     QSignalSpy stateCounter(as,
776           SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&)));
777     QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData&)));
778     QEventLoop loop;
779 
780     QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)),
781                      &loop, SLOT(quit()));
782     QObject::connect(as, SIGNAL(error(const SignOn::Error &)),
783                      &loop, SLOT(quit()));
784     QTimer::singleShot(500*1000, &loop, SLOT(quit()));
785 
786     /*
787      * chain of UiSessionData
788      * */
789     QStringList chainOfStates;
790 
791     SsoTest2PluginNS::SsoTest2Data testData;
792 
793     chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha";
794     chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha";
795     chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha";
796     chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha";
797 
798     testData.setChainOfStates(chainOfStates);
799     testData.setCurrentState(0);
800 
801     as->process(testData, "mech1");
802 
803     if (!errorCounter.count())
804         loop.exec();
805 
806     QCOMPARE(spy.count(), 1);
807     if (errorCounter.count())
808         qDebug() << errorCounter.at(0).at(1).toString();
809 
810     QCOMPARE(errorCounter.count(), 0);
811 
812 
813     SignOn::SessionData outData =
814         spy.at(0).at(0).value<SignOn::SessionData>();
815     SsoTest2PluginNS::SsoTest2Data resultData =
816         outData.data<SsoTest2PluginNS::SsoTest2Data>();
817 
818     foreach(QString result, resultData.ChainOfResults())
819         QCOMPARE(result, QString("OK"));
820 }
821 
processUi_and_cancel()822 void TestAuthSession::processUi_and_cancel()
823 {
824     AuthSession *as;
825     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest2");
826     g_currentSession = as;
827 
828     m_signOnUI->setDelay(4);
829 
830     QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &)));
831     QSignalSpy stateCounter(as,
832           SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&)));
833     QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData&)));
834     QEventLoop loop;
835 
836     QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)),
837                      &loop, SLOT(quit()));
838     QObject::connect(as, SIGNAL(error(const SignOn::Error &)),
839                      &loop, SLOT(quit()));
840     QTimer::singleShot(500*1000, &loop, SLOT(quit()));
841 
842     /*
843      * chain of UiSessionData
844      * */
845     QStringList chainOfStates;
846 
847     SsoTest2PluginNS::SsoTest2Data testData;
848 
849     chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha";
850     chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha";
851     chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha";
852     chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha";
853 
854     testData.setChainOfStates(chainOfStates);
855     testData.setCurrentState(0);
856 
857     as->process(testData, "mech1");
858     QTimer::singleShot(3*1000, this, SLOT(cancel()));
859 
860     if (!errorCounter.count())
861         loop.exec();
862 
863     QCOMPARE(spy.count(), 0);
864     QCOMPARE(errorCounter.count(), 1);
865 
866     m_signOnUI->setDelay(0);
867 }
868 
windowId()869 void TestAuthSession::windowId()
870 {
871     AuthSession *as;
872     SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest2");
873 
874     QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &)));
875     QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData&)));
876     QEventLoop loop;
877 
878     QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)),
879                      &loop, SLOT(quit()));
880     QObject::connect(as, SIGNAL(error(const SignOn::Error &)),
881                      &loop, SLOT(quit()));
882     QTimer::singleShot(500*1000, &loop, SLOT(quit()));
883 
884     /*
885      * chain of UiSessionData
886      * */
887     QStringList chainOfStates;
888 
889     SsoTest2PluginNS::SsoTest2Data testData;
890 
891     chainOfStates << "Browser" << "Browser";
892     testData.setChainOfStates(chainOfStates);
893     testData.setCurrentState(0);
894     testData.setWindowId(0xdeadbeef);
895 
896     as->process(testData, "mech1");
897     if (!errorCounter.count())
898         loop.exec();
899 
900     QCOMPARE(spy.count(), 1);
901     QCOMPARE(errorCounter.count(), 0);
902     QCOMPARE(m_signOnUI->clientData().value("WindowId").toUInt(),
903              0xdeadbeef);
904     QCOMPARE(m_signOnUI->method(), QLatin1String("ssotest2"));
905     QCOMPARE(m_signOnUI->mechanism(), QLatin1String("mech1"));
906 }
907