Skip to content

Commit 41e7d07

Browse files
committed
Unit tests for QgsCredentials
(cherry picked from commit 1699520)
1 parent ad6e156 commit 41e7d07

File tree

3 files changed

+151
-1
lines changed

3 files changed

+151
-1
lines changed

src/core/qgscredentials.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ bool QgsCredentials::get( const QString &realm, QString &username, QString &pass
4747
locker.unlock();
4848
username = credentials.first;
4949
password = credentials.second;
50+
#if 0 // don't leak credentials on log
5051
QgsDebugMsg( QStringLiteral( "retrieved realm:%1 username:%2 password:%3" ).arg( realm, username, password ) );
52+
#endif
5153

5254
if ( !password.isNull() )
5355
return true;
@@ -56,19 +58,23 @@ bool QgsCredentials::get( const QString &realm, QString &username, QString &pass
5658

5759
if ( request( realm, username, password, message ) )
5860
{
61+
#if 0 // don't leak credentials on log
5962
QgsDebugMsg( QStringLiteral( "requested realm:%1 username:%2 password:%3" ).arg( realm, username, password ) );
63+
#endif
6064
return true;
6165
}
6266
else
6367
{
64-
QgsDebugMsg( QStringLiteral( "unset realm:%1" ).arg( realm ) );
68+
QgsDebugMsgLevel( QStringLiteral( "unset realm:%1" ).arg( realm ), 4 );
6569
return false;
6670
}
6771
}
6872

6973
void QgsCredentials::put( const QString &realm, const QString &username, const QString &password )
7074
{
75+
#if 0 // don't leak credentials on log
7176
QgsDebugMsg( QStringLiteral( "inserting realm:%1 username:%2 password:%3" ).arg( realm, username, password ) );
77+
#endif
7278
QMutexLocker locker( &mMutex );
7379
mCredentialCache.insert( realm, QPair<QString, QString>( username, password ) );
7480
}

tests/src/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ SET(TESTS
9090
testcontrastenhancements.cpp
9191
testqgscoordinatereferencesystem.cpp
9292
testqgscoordinatetransform.cpp
93+
testqgscredentials.cpp
9394
testqgscurve.cpp
9495
testqgsdatadefinedsizelegend.cpp
9596
testqgsdataitem.cpp

tests/src/core/testqgscredentials.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/***************************************************************************
2+
testqgscredentials.cpp
3+
--------------------
4+
Date : February 2019
5+
Copyright : (C) 2019 by Nyall Dawson
6+
Email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
#include "qgstest.h"
16+
#include <QObject>
17+
#include <QString>
18+
#include <QtConcurrent>
19+
#include "qgscredentials.h"
20+
21+
class TestCredentials : public QgsCredentials
22+
{
23+
24+
public:
25+
TestCredentials( bool isInstance )
26+
: mExpectedRealm( QStringLiteral( "test_realm" ) )
27+
{
28+
if ( isInstance )
29+
setInstance( this );
30+
}
31+
32+
protected:
33+
bool request( const QString &realm, QString &username, QString &password, const QString & ) override
34+
{
35+
Q_ASSERT( realm == mExpectedRealm );
36+
37+
username = mUsername;
38+
password = mPassword;
39+
return true;
40+
}
41+
42+
bool requestMasterPassword( QString &, bool ) override
43+
{
44+
return true;
45+
}
46+
47+
public:
48+
QString mUsername;
49+
QString mPassword;
50+
QString mExpectedRealm;
51+
};
52+
53+
54+
class TestQgsCredentials : public QObject
55+
{
56+
Q_OBJECT
57+
58+
private slots:
59+
void initTestCase();// will be called before the first testfunction is executed.
60+
void cleanupTestCase();// will be called after the last testfunction was executed.
61+
void init() {} // will be called before each testfunction is executed.
62+
void cleanup() {} // will be called after every testfunction.
63+
void basic();
64+
void threadSafety();
65+
66+
};
67+
68+
69+
void TestQgsCredentials::initTestCase()
70+
{
71+
QgsApplication::init();
72+
QgsApplication::initQgis();
73+
}
74+
75+
void TestQgsCredentials::cleanupTestCase()
76+
{
77+
QgsApplication::exitQgis();
78+
}
79+
80+
void TestQgsCredentials::basic()
81+
{
82+
TestCredentials *t = new TestCredentials( true );
83+
QCOMPARE( QgsCredentials::instance(), t );
84+
85+
QString username;
86+
QString password;
87+
QVERIFY( QgsCredentials::instance()->get( QStringLiteral( "test_realm" ), username, password ) );
88+
QVERIFY( username.isEmpty() );
89+
QVERIFY( password.isEmpty() );
90+
91+
t->mUsername = QStringLiteral( "user" );
92+
t->mPassword = QStringLiteral( "pass" );
93+
QVERIFY( QgsCredentials::instance()->get( QStringLiteral( "test_realm" ), username, password ) );
94+
QCOMPARE( username, QStringLiteral( "user" ) );
95+
QCOMPARE( password, QStringLiteral( "pass" ) );
96+
97+
// put credential
98+
QgsCredentials::instance()->put( QStringLiteral( "test_realm" ), QStringLiteral( "user" ), QStringLiteral( "pass" ) );
99+
// TestCredentials should not be used, put credentials should be used instead
100+
t->mUsername = QStringLiteral( "user2" );
101+
t->mPassword = QStringLiteral( "pass2" );
102+
QVERIFY( QgsCredentials::instance()->get( QStringLiteral( "test_realm" ), username, password ) );
103+
QCOMPARE( username, QStringLiteral( "user" ) );
104+
QCOMPARE( password, QStringLiteral( "pass" ) );
105+
106+
t->mExpectedRealm = QStringLiteral( "test_realm2" );
107+
// should use TestCredentials again, as now cached credentials for test_realm2
108+
QVERIFY( QgsCredentials::instance()->get( QStringLiteral( "test_realm2" ), username, password ) );
109+
QCOMPARE( username, QStringLiteral( "user2" ) );
110+
QCOMPARE( password, QStringLiteral( "pass2" ) );
111+
}
112+
113+
struct GetPutCredentials
114+
{
115+
void operator()( int i )
116+
{
117+
QgsCredentials::instance()->put( QStringLiteral( "test_realm%1" ).arg( i ), QStringLiteral( "username" ), QStringLiteral( "password" ) );
118+
QString user;
119+
QString password;
120+
QVERIFY( QgsCredentials::instance()->get( QStringLiteral( "test_realm%1" ).arg( i ), user, password ) );
121+
QCOMPARE( user, QStringLiteral( "username" ) );
122+
QCOMPARE( password, QStringLiteral( "password" ) );
123+
}
124+
};
125+
126+
void TestQgsCredentials::threadSafety()
127+
{
128+
// ensure credentials storage/retrieval is thread safe
129+
TestCredentials *t = new TestCredentials( true );
130+
131+
t->mUsername = QStringLiteral( "user" );
132+
t->mPassword = QStringLiteral( "pass" );
133+
134+
// smash credentials rendering over multiple threads
135+
QVector< int > list;
136+
list.resize( 1000 );
137+
for ( int i = 0; i < list.size(); ++i )
138+
list[i] = i;
139+
QtConcurrent::blockingMap( list, GetPutCredentials() );
140+
}
141+
142+
QGSTEST_MAIN( TestQgsCredentials )
143+
#include "testqgscredentials.moc"

0 commit comments

Comments
 (0)