~ubuntu-branches/ubuntu/quantal/kde-runtime/quantal

« back to all changes in this revision

Viewing changes to kpasswdserver/tests/kpasswdservertest.cpp

  • Committer: Package Import Robot
  • Author(s): Philip Muškovac
  • Date: 2012-06-03 21:50:00 UTC
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: package-import@ubuntu.com-20120603215000-vn7oarsq0ynrydj5
Tags: upstream-4.8.80
Import upstream version 4.8.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* This file is part of the KDE project
2
2
    Copyright 2010 David Faure <faure@kde.org>
 
3
    Copyright 2012 Dawit Alemayehu <adawit@kde.org>
3
4
 
4
5
   This program is free software; you can redistribute it and/or modify
5
6
   it under the terms of the GNU General Public License as published by
26
27
static const char* sigQueryAuthInfoResult = SIGNAL(queryAuthInfoAsyncResult(qlonglong,qlonglong,KIO::AuthInfo));
27
28
static const char* sigCheckAuthInfoResult = SIGNAL(checkAuthInfoAsyncResult(qlonglong,qlonglong,KIO::AuthInfo));
28
29
 
 
30
static QString getUserNameFrom(const KIO::AuthInfo& auth)
 
31
{
 
32
    if (auth.username.isEmpty() && !auth.url.user().isEmpty()) {
 
33
        return auth.url.user();
 
34
    }
 
35
 
 
36
    return auth.username;
 
37
}
 
38
 
29
39
class KPasswdServerTest : public QObject
30
40
{
31
41
    Q_OBJECT
38
48
    void simpleTest()
39
49
    {
40
50
        KPasswdServer server(this);
 
51
        server.setWalletDisabled(true);
41
52
 
42
53
        // Check that processRequest doesn't crash when it has nothing to do
43
54
        server.processRequest();
75
86
    void testCheckDuringQuery()
76
87
    {
77
88
        KPasswdServer server(this);
 
89
        server.setWalletDisabled(true);
78
90
        KIO::AuthInfo info;
79
91
        info.url = KUrl("http://www.kde.org");
80
92
 
107
119
        QCOMPARE(result.password, resultCheck.password);
108
120
    }
109
121
 
110
 
    // TODO check closing the window and auth should be cleared (keepPassword=false) or kept (keepPassword=true)
111
122
    void testExpiry()
112
123
    {
113
124
        KPasswdServer server(this);
 
125
        server.setWalletDisabled(true);
114
126
        KIO::AuthInfo info;
115
127
        info.url = KUrl("http://www.example.com");
116
128
 
137
149
    void testFillDialog()
138
150
    {
139
151
        KPasswdServer server(this);
 
152
        server.setWalletDisabled(true);
140
153
        // What the app would ask
141
154
        KIO::AuthInfo info;
142
155
        info.url = KUrl("http://www.example.com");
150
163
        queryAuthWithDialog(server, info, filledInfo, result);
151
164
    }
152
165
 
153
 
    // TODO test cancelling
154
 
    // TODO test more concurrent requests
155
 
    // TODO set info.verifyPath
 
166
    void testRetryDialog()
 
167
    {
 
168
        KPasswdServer server(this);
 
169
        server.setWalletDisabled(true);
 
170
 
 
171
       // What the app would ask
 
172
        KIO::AuthInfo info;
 
173
        info.url = KUrl("http://www.example.com");
 
174
 
 
175
        // What the user would type
 
176
        KIO::AuthInfo filledInfo(info);
 
177
        filledInfo.username = "username";
 
178
        filledInfo.password = "password";
 
179
 
 
180
        KIO::AuthInfo result;
 
181
        queryAuthWithDialog(server, info, filledInfo, result);
 
182
 
 
183
        // Pretend that the returned credentials failed and initiate a retry,
 
184
        // but cancel the retry dialog.
 
185
        info.password.clear();
 
186
        result = KIO::AuthInfo();
 
187
        queryAuthWithDialog(server, info, filledInfo, result, QDialog::Rejected, QLatin1String("Invalid username or password"));
 
188
 
 
189
        // Pretend that the returned credentials failed and initiate a retry,
 
190
        // but this time continue the retry.
 
191
        info.password.clear();
 
192
        result = KIO::AuthInfo();
 
193
        queryAuthWithDialog(server, info, filledInfo, result, QDialog::Accepted, QLatin1String("Invalid username or password"));
 
194
    }
 
195
 
 
196
    void testUsernameMistmatch()
 
197
    {
 
198
        KPasswdServer server(this);
 
199
        server.setWalletDisabled(true);
 
200
 
 
201
        // What the app would ask. Note the username in the URL.
 
202
        KIO::AuthInfo info;
 
203
        info.url = KUrl("http://foo@www.example.com");
 
204
 
 
205
        // What the user would type
 
206
        KIO::AuthInfo filledInfo(info);
 
207
        filledInfo.username = "bar";
 
208
        filledInfo.password = "blah";
 
209
 
 
210
        KIO::AuthInfo result;
 
211
        queryAuthWithDialog(server, info, filledInfo, result);
 
212
 
 
213
        // Check the returned url does not match the request url because of the
 
214
        // username mismatch between the request URL and the filled in one.
 
215
        QVERIFY(result.url != filledInfo.url);
 
216
 
 
217
        // Verify there is NO cached auth data if the request URL contains the
 
218
        // original user name (foo).
 
219
        QVERIFY(noCheckAuth(server, info));
 
220
 
 
221
        // Verify there is a cached auth data if the request URL contains the
 
222
        // new user name (bar).
 
223
        filledInfo.url = KUrl("http://bar@www.example.com");
 
224
        QVERIFY(successCheckAuth(server, filledInfo, result));
 
225
 
 
226
        // Now the URL check should be valid too.
 
227
        QCOMPARE(result.url, filledInfo.url);
 
228
    }
 
229
 
 
230
    void testCancelPasswordDialog()
 
231
    {
 
232
        KPasswdServer server(this);
 
233
        server.setWalletDisabled(true);
 
234
 
 
235
        // What the app would ask.
 
236
        KIO::AuthInfo info;
 
237
        info.url = KUrl("http://www.example.com");
 
238
        info.username = info.url.user();
 
239
 
 
240
        KIO::AuthInfo result;
 
241
        queryAuthWithDialog(server, info, KIO::AuthInfo(), result, QDialog::Rejected);
 
242
    }
 
243
 
 
244
    void testVerifyPath()
 
245
    {
 
246
        KPasswdServer server(this);
 
247
        server.setWalletDisabled(true);
 
248
 
 
249
        // Add auth to the cache
 
250
        const qlonglong windowId = 42;
 
251
        KIO::AuthInfo authInfo;
 
252
        authInfo.url = KUrl("http://www.example.com/test/test.html");
 
253
        authInfo.username = "toto";
 
254
        authInfo.password = "foobar";
 
255
        server.addAuthInfo(authInfo, windowId);
 
256
 
 
257
        KIO::AuthInfo queryAuthInfo;
 
258
        queryAuthInfo.url = KUrl("http://www.example.com/test/test2/test.html");
 
259
        queryAuthInfo.verifyPath = true;
 
260
 
 
261
        KIO::AuthInfo expectedAuthInfo;
 
262
        expectedAuthInfo.username = "toto";
 
263
        expectedAuthInfo.password = "foobar";
 
264
 
 
265
        QVERIFY(successCheckAuth(server, queryAuthInfo, expectedAuthInfo));
 
266
    }
 
267
 
 
268
    void testConcurrentQueryAuth()
 
269
    {
 
270
        KPasswdServer server(this);
 
271
        server.setWalletDisabled(true);
 
272
 
 
273
        QList<KIO::AuthInfo> authInfos;
 
274
        for (int i=0; i < 10; ++i) {
 
275
           KIO::AuthInfo info;
 
276
           info.url = KUrl("http://www.example.com/test" + QString::number(i) + ".html");
 
277
           authInfos << info;
 
278
        }
 
279
 
 
280
        // What the user would type
 
281
        KIO::AuthInfo filledInfo;
 
282
        filledInfo.username = "bar";
 
283
        filledInfo.password = "blah";
 
284
 
 
285
        QList<KIO::AuthInfo> results;
 
286
        concurrentQueryAuthWithDialog(server, authInfos, filledInfo, results);
 
287
    }
 
288
 
 
289
    void testConcurrentCheckAuth()
 
290
    {
 
291
        KPasswdServer server(this);
 
292
        server.setWalletDisabled(true);
 
293
 
 
294
        QList<KIO::AuthInfo> authInfos;
 
295
        for (int i=0; i < 10; ++i) {
 
296
           KIO::AuthInfo info;
 
297
           info.url = KUrl("http://www.example.com/test" + QString::number(i) + ".html");
 
298
           authInfos << info;
 
299
        }
 
300
 
 
301
        // What the user would type
 
302
        KIO::AuthInfo filledInfo;
 
303
        filledInfo.username = "bar";
 
304
        filledInfo.password = "blah";
 
305
 
 
306
        QList<KIO::AuthInfo> results;
 
307
        concurrentQueryAuthWithDialog(server, authInfos, filledInfo, results);
 
308
    }
156
309
 
157
310
private:
158
311
    // Checks that no auth is available for @p info
200
353
            info,
201
354
            QString("<NoAuthPrompt>"), // magic string to avoid a dialog
202
355
            windowId, seqNr, 16 /*usertime*/);
203
 
        QVERIFY(id > 0); // requestId, ever increasing
 
356
        QVERIFY(id >= 0); // requestId, ever increasing
204
357
        if (spy.isEmpty())
205
358
            QVERIFY(QTest::kWaitForSignal(&server, sigQueryAuthInfoResult, 1000));
206
359
        QCOMPARE(spy.count(), 1);
209
362
        result = spy[0][2].value<KIO::AuthInfo>();
210
363
    }
211
364
 
212
 
    void queryAuthWithDialog(KPasswdServer& server, const KIO::AuthInfo& info, const KIO::AuthInfo& filledInfo, KIO::AuthInfo& result)
 
365
    void queryAuthWithDialog(KPasswdServer& server, const KIO::AuthInfo& info,
 
366
                             const KIO::AuthInfo& filledInfo, KIO::AuthInfo& result,
 
367
                             int code = QDialog::Accepted, const QString& errMsg = QString())
213
368
    {
214
369
        QSignalSpy spy(&server, sigQueryAuthInfoResult);
215
370
        const qlonglong windowId = 42;
216
371
        const qlonglong seqNr = 2;
217
372
        const qlonglong id = server.queryAuthInfoAsync(
218
373
            info,
219
 
            QString("KPasswdServerTest"),
 
374
            errMsg,
220
375
            windowId, seqNr, 16 /*usertime*/);
221
 
        QVERIFY(id > 0); // requestId, ever increasing
 
376
        QVERIFY(id >= 0); // requestId, ever increasing
222
377
        QVERIFY(spy.isEmpty());
223
 
        QMetaObject::invokeMethod(this, "checkAndFillDialog", Qt::QueuedConnection, Q_ARG(KIO::AuthInfo, info), Q_ARG(KIO::AuthInfo, filledInfo));
 
378
 
 
379
        const bool hasErrorMessage = (!errMsg.isEmpty());
 
380
        const bool isCancelRetryDialogTest = (hasErrorMessage && code == QDialog::Rejected);
 
381
 
 
382
        if (hasErrorMessage) {
 
383
            QMetaObject::invokeMethod(this, "checkRetryDialog",
 
384
                                      Qt::QueuedConnection, Q_ARG(int, code));
 
385
        }
 
386
 
 
387
        if (!isCancelRetryDialogTest) {
 
388
            QMetaObject::invokeMethod(this, "checkAndFillDialog", Qt::QueuedConnection,
 
389
                                      Q_ARG(KIO::AuthInfo, info),
 
390
                                      Q_ARG(KIO::AuthInfo, filledInfo),
 
391
                                      Q_ARG(int, code));
 
392
        }
224
393
        // Force KPasswdServer to process the request now, otherwise the checkAndFillDialog needs a timer too...
225
394
        server.processRequest();
 
395
        if (spy.isEmpty())
 
396
            QVERIFY(QTest::kWaitForSignal(&server, sigQueryAuthInfoResult, 1000));
226
397
        QCOMPARE(spy.count(), 1);
227
398
        QCOMPARE(spy[0][0].toLongLong(), id);
228
399
        //QCOMPARE(spy[0][1].toLongLong(), 3LL); // seqNr
229
400
        result = spy[0][2].value<KIO::AuthInfo>();
230
 
        QCOMPARE(result.username, filledInfo.username);
231
 
        QCOMPARE(result.password, filledInfo.password);
232
 
        QCOMPARE(result.isModified(), true);
 
401
        QCOMPARE(result.username, (isCancelRetryDialogTest ? QString() : filledInfo.username));
 
402
        QCOMPARE(result.password, (isCancelRetryDialogTest ? QString() : filledInfo.password));
 
403
        QCOMPARE(result.isModified(), (code == QDialog::Accepted ? true : false));
 
404
    }
 
405
 
 
406
    void concurrentQueryAuthWithDialog(KPasswdServer& server, const QList<KIO::AuthInfo>& infos,
 
407
                                       const KIO::AuthInfo& filledInfo, QList<KIO::AuthInfo>& results,
 
408
                                       int code = QDialog::Accepted)
 
409
    {
 
410
        QSignalSpy spy(&server, sigQueryAuthInfoResult);
 
411
        const qlonglong windowId = 42;
 
412
        qlonglong seqNr = 0;
 
413
        QList<qlonglong> idList;
 
414
 
 
415
        Q_FOREACH(const KIO::AuthInfo& info, infos) {
 
416
            const qlonglong id = server.queryAuthInfoAsync(
 
417
                info,
 
418
                QString(),
 
419
                windowId, seqNr, 16 /*usertime*/);
 
420
            QVERIFY(id >= 0); // requestId, ever increasing
 
421
            idList << id;
 
422
        }
 
423
 
 
424
        QVERIFY(spy.isEmpty());
 
425
        QMetaObject::invokeMethod(this, "checkAndFillDialog", Qt::QueuedConnection,
 
426
                                  Q_ARG(KIO::AuthInfo, infos.first()),
 
427
                                  Q_ARG(KIO::AuthInfo,filledInfo),
 
428
                                  Q_ARG(int, code));
 
429
 
 
430
        // Force KPasswdServer to process the request now, otherwise the checkAndFillDialog needs a timer too...
 
431
        server.processRequest();
 
432
        while (spy.count() < infos.count())
 
433
            QVERIFY(QTest::kWaitForSignal(&server, sigQueryAuthInfoResult, 1000));
 
434
 
 
435
        QCOMPARE(spy.count(), infos.count());
 
436
 
 
437
        for(int i = 0, count = spy.count(); i < count; ++i) {
 
438
            QCOMPARE(spy[i][0].toLongLong(), idList.at(i));
 
439
            //QCOMPARE(spy[0][1].toLongLong(), 3LL); // seqNr
 
440
            KIO::AuthInfo result = spy[i][2].value<KIO::AuthInfo>();
 
441
            QCOMPARE(result.username, filledInfo.username);
 
442
            QCOMPARE(result.password, filledInfo.password);
 
443
            QCOMPARE(result.isModified(), (code == QDialog::Accepted ? true : false));
 
444
            results << result;
 
445
        }
 
446
    }
 
447
 
 
448
    void concurrentCheckAuthWithDialog(KPasswdServer& server, const QList<KIO::AuthInfo>& infos,
 
449
                                       const KIO::AuthInfo& filledInfo, QList<KIO::AuthInfo>& results,
 
450
                                       int code = QDialog::Accepted)
 
451
    {
 
452
        QSignalSpy spy(&server, sigQueryAuthInfoResult);
 
453
        const qlonglong windowId = 42;
 
454
        qlonglong seqNr = 0;
 
455
        QList<qlonglong> idList;
 
456
 
 
457
        QListIterator<KIO::AuthInfo> it (infos);
 
458
        if (it.hasNext()) {
 
459
            const qlonglong id = server.queryAuthInfoAsync(
 
460
                it.next(),
 
461
                QString(),
 
462
                windowId, seqNr, 16 /*usertime*/);
 
463
            QVERIFY(id >= 0); // requestId, ever increasing
 
464
            idList << id;
 
465
        }
 
466
 
 
467
        while (it.hasNext()) {
 
468
            const qlonglong id = server.checkAuthInfoAsync(it.next(), windowId,16 /*usertime*/);
 
469
            QVERIFY(id >= 0); // requestId, ever increasing
 
470
            idList << id;
 
471
        }
 
472
 
 
473
        QVERIFY(spy.isEmpty());
 
474
        QMetaObject::invokeMethod(this, "checkAndFillDialog", Qt::QueuedConnection,
 
475
                                  Q_ARG(KIO::AuthInfo, infos.first()),
 
476
                                  Q_ARG(KIO::AuthInfo,filledInfo),
 
477
                                  Q_ARG(int, code));
 
478
 
 
479
        // Force KPasswdServer to process the request now, otherwise the checkAndFillDialog needs a timer too...
 
480
        server.processRequest();
 
481
        if (spy.isEmpty())
 
482
            QVERIFY(QTest::kWaitForSignal(&server, sigQueryAuthInfoResult, 1000));
 
483
 
 
484
        while ((spy.count()-1) < infos.count()) {
 
485
            QVERIFY(QTest::kWaitForSignal(&server, sigCheckAuthInfoResult, 1000));
 
486
        }
 
487
 
 
488
        for(int i = 0, count = spy.count(); i < count; ++i) {
 
489
            QCOMPARE(spy[i][0].toLongLong(), idList.at(i));
 
490
            //QCOMPARE(spy[0][1].toLongLong(), 3LL); // seqNr
 
491
            KIO::AuthInfo result = spy[i][2].value<KIO::AuthInfo>();
 
492
            QCOMPARE(result.username, filledInfo.username);
 
493
            QCOMPARE(result.password, filledInfo.password);
 
494
            QCOMPARE(result.isModified(), (code == QDialog::Accepted ? true : false));
 
495
            results << result;
 
496
        }
233
497
    }
234
498
 
235
499
protected Q_SLOTS:
236
 
    void checkAndFillDialog(const KIO::AuthInfo& info, const KIO::AuthInfo& filledInfo)
 
500
    void checkAndFillDialog(const KIO::AuthInfo& info, const KIO::AuthInfo& filledInfo, int code = QDialog::Accepted)
237
501
    {
238
502
        Q_FOREACH(QWidget *widget, QApplication::topLevelWidgets()) {
239
 
            kDebug() << widget;
240
503
            if (KPasswordDialog* dialog = qobject_cast<KPasswordDialog *>(widget)) {
241
 
                QCOMPARE(dialog->username(), info.username);
242
 
                QCOMPARE(dialog->password(), info.password);
243
 
                dialog->setUsername(filledInfo.username);
244
 
                dialog->setPassword(filledInfo.password);
245
 
                dialog->done(QDialog::Accepted);
 
504
                if (code == QDialog::Accepted) {
 
505
                    QCOMPARE(dialog->username(), getUserNameFrom(info));
 
506
                    QCOMPARE(dialog->password(), info.password);
 
507
                    dialog->setUsername(filledInfo.username);
 
508
                    dialog->setPassword(filledInfo.password);
 
509
                }
 
510
                dialog->done(code);
246
511
                return;
247
512
            }
248
513
        }
249
514
        kWarning() << "No KPasswordDialog found!";
250
515
    }
 
516
 
 
517
    void checkRetryDialog(int code = QDialog::Accepted)
 
518
    {
 
519
        Q_FOREACH(QWidget *widget, QApplication::topLevelWidgets()) {
 
520
            KDialog* dialog = qobject_cast<KDialog*>(widget);
 
521
            if (dialog && !dialog->inherits("KPasswordDialog")) {
 
522
                dialog->done(code);
 
523
                return;
 
524
            }
 
525
        }
 
526
    }
251
527
};
252
528
 
253
529
QTEST_KDEMAIN( KPasswdServerTest, GUI )