Merge lp:~online-accounts/signon-plugin-oauth2/packaging into lp:signon-plugin-oauth2
- packaging
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | David Barth |
Approved revision: | no longer in the source branch. |
Merged at revision: | 76 |
Proposed branch: | lp:~online-accounts/signon-plugin-oauth2/packaging |
Merge into: | lp:signon-plugin-oauth2 |
Diff against target: |
1366 lines (+360/-295) 8 files modified
common-vars.pri (+1/-1) debian/changelog (+9/-0) src/oauth2data.h (+4/-0) src/oauth2plugin.cpp (+48/-29) src/src.pro (+1/-9) tests/oauth2plugintest.cpp (+296/-236) tests/oauth2plugintest.h (+0/-12) tests/tests.pro (+1/-8) |
To merge this branch: | bzr merge lp:~online-accounts/signon-plugin-oauth2/packaging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Online Accounts | Pending | ||
Review via email: mp+256492@code.launchpad.net |
Commit message
Merge from upstream:
- Return the list of granted permissions to the client
- Require Qt5 for building
- Use a "state" parameter to protect against CSRF (LP: #1432857)
Description of the change
Merge from upstream:
- Return the list of granted permissions to the client
- Require Qt5 for building
- Use a "state" parameter to protect against CSRF (LP: #1432857)
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:78
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 76. By Alberto Mardegan
-
Merge from upstream:
- Return the list of granted permissions to the client
- Require Qt5 for building
- Use a "state" parameter to protect against CSRF (LP: #1432857)Approved by: PS Jenkins bot
Preview Diff
1 | === modified file 'common-vars.pri' |
2 | --- common-vars.pri 2015-01-28 11:12:16 +0000 |
3 | +++ common-vars.pri 2015-04-17 08:14:56 +0000 |
4 | @@ -13,7 +13,7 @@ |
5 | # Project version |
6 | # remember to update debian/* files if you changes this |
7 | #----------------------------------------------------------------------------- |
8 | -PROJECT_VERSION = 0.21 |
9 | +PROJECT_VERSION = 0.22 |
10 | |
11 | #----------------------------------------------------------------------------- |
12 | # Library version |
13 | |
14 | === modified file 'debian/changelog' |
15 | --- debian/changelog 2015-03-27 11:12:54 +0000 |
16 | +++ debian/changelog 2015-04-17 08:14:56 +0000 |
17 | @@ -1,3 +1,12 @@ |
18 | +signon-plugin-oauth2 (0.22-0ubuntu1) UNRELEASED; urgency=medium |
19 | + |
20 | + * New upstream release |
21 | + - Return the list of granted permissions to the client |
22 | + - Require Qt5 for building |
23 | + - Use a "state" parameter to protect against CSRF (LP: #1432857) |
24 | + |
25 | + -- Alberto Mardegan <alberto.mardegan@canonical.com> Thu, 16 Apr 2015 16:42:35 +0300 |
26 | + |
27 | signon-plugin-oauth2 (0.21+15.04.20150327-0ubuntu1) vivid; urgency=medium |
28 | |
29 | * New rebuild forced. |
30 | |
31 | === modified file 'src/oauth2data.h' |
32 | --- src/oauth2data.h 2014-10-31 08:09:57 +0000 |
33 | +++ src/oauth2data.h 2015-04-17 08:14:56 +0000 |
34 | @@ -106,6 +106,10 @@ |
35 | * Access token expiry time |
36 | */ |
37 | SIGNON_SESSION_DECLARE_PROPERTY(int, ExpiresIn); |
38 | + /*! |
39 | + * Granted permissions |
40 | + */ |
41 | + SIGNON_SESSION_DECLARE_PROPERTY(QStringList, Scope); |
42 | }; |
43 | |
44 | } // namespace OAuth2PluginNS |
45 | |
46 | === modified file 'src/oauth2plugin.cpp' |
47 | --- src/oauth2plugin.cpp 2015-02-16 13:37:52 +0000 |
48 | +++ src/oauth2plugin.cpp 2015-04-17 08:14:56 +0000 |
49 | @@ -25,18 +25,13 @@ |
50 | #include "oauth2plugin.h" |
51 | #include "oauth2tokendata.h" |
52 | |
53 | +#include <QJsonDocument> |
54 | #include <QUrl> |
55 | +#include <QUrlQuery> |
56 | #include <QNetworkRequest> |
57 | #include <QNetworkReply> |
58 | #include <QDateTime> |
59 | |
60 | -#define USE_LIBQJSON (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) |
61 | - |
62 | -#if USE_LIBQJSON |
63 | -#include <qjson/parser.h> |
64 | -#else |
65 | -#include <QJsonDocument> |
66 | -#endif |
67 | |
68 | using namespace SignOn; |
69 | using namespace OAuth2PluginNS; |
70 | @@ -54,6 +49,7 @@ |
71 | const QString AUTH_CODE = QString("code"); |
72 | const QString REDIRECT_URI = QString("redirect_uri"); |
73 | const QString RESPONSE_TYPE = QString("response_type"); |
74 | +const QString STATE = QString("state"); |
75 | const QString USERNAME = QString("username"); |
76 | const QString PASSWORD = QString("password"); |
77 | const QString ASSERTION_TYPE = QString("assertion_type"); |
78 | @@ -61,6 +57,7 @@ |
79 | const QString ACCESS_TOKEN = QString("access_token"); |
80 | const QString DISPLAY = QString("display"); |
81 | const QString EXPIRES_IN = QString("expires_in"); |
82 | +const QString SCOPE = QString("scope"); |
83 | const QString TIMESTAMP = QString("timestamp"); |
84 | const QString GRANT_TYPE = QString("grant_type"); |
85 | const QString AUTHORIZATION_CODE = QString("authorization_code"); |
86 | @@ -96,6 +93,7 @@ |
87 | QString m_mechanism; |
88 | OAuth2PluginData m_oauth2Data; |
89 | QVariantMap m_tokens; |
90 | + QString m_state; |
91 | QString m_key; |
92 | QString m_username; |
93 | QString m_password; |
94 | @@ -133,6 +131,8 @@ |
95 | QUrl url(QString("https://%1/%2").arg(d->m_oauth2Data.Host()).arg(d->m_oauth2Data.AuthPath())); |
96 | url.addQueryItem(CLIENT_ID, d->m_oauth2Data.ClientId()); |
97 | url.addQueryItem(REDIRECT_URI, d->m_oauth2Data.RedirectUri()); |
98 | + d->m_state = QString::number(qrand()); |
99 | + url.addQueryItem(STATE, d->m_state); |
100 | if (!d->m_oauth2Data.ResponseType().isEmpty()) { |
101 | url.addQueryItem(RESPONSE_TYPE, |
102 | d->m_oauth2Data.ResponseType().join(" ")); |
103 | @@ -153,7 +153,7 @@ |
104 | } |
105 | |
106 | // Passing list of scopes |
107 | - url.addQueryItem(QString("scope"), d->m_oauth2Data.Scope().join(separator)); |
108 | + url.addQueryItem(SCOPE, d->m_oauth2Data.Scope().join(separator)); |
109 | } |
110 | TRACE() << "Url = " << url.toString(); |
111 | SignOn::UiSessionData uiSession; |
112 | @@ -360,21 +360,30 @@ |
113 | if (d->m_mechanism == USER_AGENT) { |
114 | // Response should contain the access token |
115 | OAuth2PluginTokenData respData; |
116 | - QString fragment; |
117 | if (url.hasFragment()) { |
118 | - fragment = url.fragment(); |
119 | - QStringList list = fragment.split(QRegExp("&|="), QString::SkipEmptyParts); |
120 | - for (int i = 1; i < list.count(); i += 2) { |
121 | - if (list.at(i - 1) == ACCESS_TOKEN) { |
122 | - respData.setAccessToken(list.at(i)); |
123 | - } |
124 | - else if (list.at(i - 1) == EXPIRES_IN) { |
125 | - respData.setExpiresIn(QString(list.at(i)).toInt()); |
126 | - } |
127 | - else if (list.at(i - 1) == REFRESH_TOKEN) { |
128 | - respData.setRefreshToken(list.at(i)); |
129 | - } |
130 | - } |
131 | + QString state; |
132 | + respData.setScope(d->m_oauth2Data.Scope()); |
133 | + QUrlQuery fragment(url.fragment()); |
134 | + typedef QPair<QString, QString> StringPair; |
135 | + Q_FOREACH(const StringPair &pair, fragment.queryItems()) { |
136 | + if (pair.first == ACCESS_TOKEN) { |
137 | + respData.setAccessToken(pair.second); |
138 | + } else if (pair.first == EXPIRES_IN) { |
139 | + respData.setExpiresIn(pair.second.toInt()); |
140 | + } else if (pair.first == REFRESH_TOKEN) { |
141 | + respData.setRefreshToken(pair.second); |
142 | + } else if (pair.first == STATE) { |
143 | + state = pair.second; |
144 | + } else if (pair.first == SCOPE) { |
145 | + respData.setScope(pair.second.split(' ', QString::SkipEmptyParts)); |
146 | + } |
147 | + } |
148 | + if (state != d->m_state) { |
149 | + Q_EMIT error(Error(Error::NotAuthorized, |
150 | + QString("'state' parameter mismatch"))); |
151 | + return; |
152 | + } |
153 | + |
154 | if (respData.AccessToken().isEmpty()) { |
155 | emit error(Error(Error::NotAuthorized, QString("Access token not present"))); |
156 | } else { |
157 | @@ -394,6 +403,11 @@ |
158 | // 4. Refresh Token (refresh_token) |
159 | QUrl newUrl; |
160 | if (url.hasQueryItem(AUTH_CODE)) { |
161 | + if (d->m_state != url.queryItemValue(STATE)) { |
162 | + Q_EMIT error(Error(Error::NotAuthorized, |
163 | + QString("'state' parameter mismatch"))); |
164 | + return; |
165 | + } |
166 | QString code = url.queryItemValue(AUTH_CODE); |
167 | newUrl.addQueryItem(GRANT_TYPE, AUTHORIZATION_CODE); |
168 | newUrl.addQueryItem(AUTH_CODE, code); |
169 | @@ -473,6 +487,8 @@ |
170 | // Method to handle responses for OAuth 2.0 requests |
171 | void OAuth2Plugin::serverReply(QNetworkReply *reply) |
172 | { |
173 | + Q_D(OAuth2Plugin); |
174 | + |
175 | QByteArray replyContent = reply->readAll(); |
176 | TRACE() << replyContent; |
177 | |
178 | @@ -499,6 +515,14 @@ |
179 | } |
180 | QByteArray refreshToken = map["refresh_token"].toByteArray(); |
181 | |
182 | + QStringList scope; |
183 | + if (map.contains(SCOPE)) { |
184 | + QString rawScope = QString::fromUtf8(map[SCOPE].toByteArray()); |
185 | + scope = rawScope.split(' ', QString::SkipEmptyParts); |
186 | + } else { |
187 | + scope = d->m_oauth2Data.Scope(); |
188 | + } |
189 | + |
190 | if (accessToken.isEmpty()) { |
191 | TRACE()<< "Access token is empty"; |
192 | Q_EMIT error(Error(Error::NotAuthorized, |
193 | @@ -508,6 +532,7 @@ |
194 | response.setAccessToken(accessToken); |
195 | response.setRefreshToken(refreshToken); |
196 | response.setExpiresIn(expiresIn); |
197 | + response.setScope(scope); |
198 | storeResponse(response); |
199 | emit result(response); |
200 | } |
201 | @@ -676,15 +701,9 @@ |
202 | QVariantMap OAuth2Plugin::parseJSONReply(const QByteArray &reply) |
203 | { |
204 | TRACE(); |
205 | - bool ok = false; |
206 | -#if USE_LIBQJSON |
207 | - QJson::Parser parser; |
208 | - QVariant tree = parser.parse(reply, &ok); |
209 | -#else |
210 | QJsonDocument doc = QJsonDocument::fromJson(reply); |
211 | - ok = !doc.isEmpty(); |
212 | + bool ok = !doc.isEmpty(); |
213 | QVariant tree = doc.toVariant(); |
214 | -#endif |
215 | if (ok) { |
216 | return tree.toMap(); |
217 | } |
218 | |
219 | === modified file 'src/src.pro' |
220 | --- src/src.pro 2013-04-26 09:12:55 +0000 |
221 | +++ src/src.pro 2015-04-17 08:14:56 +0000 |
222 | @@ -27,17 +27,9 @@ |
223 | oauth2plugin.cpp \ |
224 | plugin.cpp |
225 | PKGCONFIG += \ |
226 | + libsignon-qt5 \ |
227 | signon-plugins |
228 | |
229 | -lessThan(QT_MAJOR_VERSION, 5) { |
230 | - PKGCONFIG += \ |
231 | - QJson \ |
232 | - libsignon-qt |
233 | -} else { |
234 | - PKGCONFIG += \ |
235 | - libsignon-qt5 |
236 | -} |
237 | - |
238 | headers.files = $$public_headers |
239 | pkgconfig.files = signon-oauth2plugin.pc |
240 | include( ../common-installs-config.pri ) |
241 | |
242 | === modified file 'tests/oauth2plugintest.cpp' |
243 | --- tests/oauth2plugintest.cpp 2015-02-16 12:25:29 +0000 |
244 | +++ tests/oauth2plugintest.cpp 2015-04-17 08:14:56 +0000 |
245 | @@ -21,10 +21,13 @@ |
246 | * 02110-1301 USA |
247 | */ |
248 | |
249 | +#include <QJsonDocument> |
250 | +#include <QJsonObject> |
251 | #include <QNetworkAccessManager> |
252 | #include <QNetworkReply> |
253 | #include <QPointer> |
254 | #include <QRegExp> |
255 | +#include <QSignalSpy> |
256 | #include <QTimer> |
257 | #include <QtTest/QtTest> |
258 | |
259 | @@ -38,6 +41,22 @@ |
260 | using namespace OAuth2PluginNS; |
261 | using namespace SignOn; |
262 | |
263 | +namespace QTest { |
264 | +template<> |
265 | +char *toString(const QVariantMap &map) |
266 | +{ |
267 | + QJsonDocument doc(QJsonObject::fromVariantMap(map)); |
268 | + return qstrdup(doc.toJson(QJsonDocument::Compact).data()); |
269 | +} |
270 | +} // QTest namespace |
271 | + |
272 | +static QString parseState(const QSignalSpy &userActionRequired) |
273 | +{ |
274 | + UiSessionData data = userActionRequired.at(0).at(0).value<UiSessionData>(); |
275 | + QUrlQuery query(data.OpenUrl()); |
276 | + return query.queryItemValue("state"); |
277 | +} |
278 | + |
279 | static bool mapIsSubset(const QVariantMap &set, const QVariantMap &test) |
280 | { |
281 | QMapIterator<QString, QVariant> it(set); |
282 | @@ -190,10 +209,6 @@ |
283 | void OAuth2PluginTest::init() |
284 | { |
285 | m_testPlugin = new Plugin(); |
286 | - m_stored = SignOn::SessionData(); |
287 | - m_response = SignOn::SessionData(); |
288 | - m_uiResponse = SignOn::UiSessionData(); |
289 | - m_error = SignOn::Error(-1); |
290 | } |
291 | |
292 | //finnish each test by deleting plugin |
293 | @@ -203,43 +218,6 @@ |
294 | m_testPlugin=NULL; |
295 | } |
296 | |
297 | -//slot for receiving result |
298 | -void OAuth2PluginTest::result(const SignOn::SessionData& data) |
299 | -{ |
300 | - m_response = data; |
301 | - m_loop.exit(); |
302 | -} |
303 | - |
304 | -//slot for receiving error |
305 | -void OAuth2PluginTest::pluginError(const SignOn::Error &err) |
306 | -{ |
307 | - m_error = err; |
308 | - m_loop.exit(); |
309 | -} |
310 | - |
311 | -//slot for receiving result |
312 | -void OAuth2PluginTest::uiRequest(const SignOn::UiSessionData& data) |
313 | -{ |
314 | - Q_UNUSED(data); |
315 | - m_uiResponse.setUrlResponse(QString("UI request received")); |
316 | - m_loop.exit(); |
317 | -} |
318 | - |
319 | -//slot for store |
320 | -void OAuth2PluginTest::store(const SignOn::SessionData &data) |
321 | -{ |
322 | - m_stored = data; |
323 | -} |
324 | - |
325 | -void OAuth2PluginTest::aborted(QNetworkReply* reply) |
326 | -{ |
327 | - qDebug() << "aborted"; |
328 | - //we should get error code if request was aborted |
329 | - qDebug() << reply->error(); |
330 | - QVERIFY(reply->error()); |
331 | - m_loop.exit(); |
332 | -} |
333 | - |
334 | // TEST CASES |
335 | void OAuth2PluginTest::testPlugin() |
336 | { |
337 | @@ -261,15 +239,11 @@ |
338 | |
339 | void OAuth2PluginTest::testPluginCancel() |
340 | { |
341 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
342 | - |
343 | //does nothing as no active connections |
344 | m_testPlugin->cancel(); |
345 | |
346 | //then real cancel |
347 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error &)), |
348 | - this, SLOT(pluginError(const SignOn::Error &)), |
349 | - Qt::QueuedConnection); |
350 | + QSignalSpy pluginError(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
351 | |
352 | OAuth2PluginData userAgentData; |
353 | userAgentData.setHost("https://localhost"); |
354 | @@ -280,8 +254,9 @@ |
355 | |
356 | m_testPlugin->process(userAgentData, QString("user_agent")); |
357 | m_testPlugin->cancel(); |
358 | - m_loop.exec(); |
359 | - QCOMPARE(m_error.type(), int(Error::SessionCanceled)); |
360 | + QTRY_COMPARE(pluginError.count(), 1); |
361 | + Error error = pluginError.at(0).at(0).value<Error>(); |
362 | + QCOMPARE(error.type(), int(Error::SessionCanceled)); |
363 | } |
364 | |
365 | void OAuth2PluginTest::testPluginProcess_data() |
366 | @@ -289,7 +264,7 @@ |
367 | QTest::addColumn<QString>("mechanism"); |
368 | QTest::addColumn<QVariantMap>("sessionData"); |
369 | QTest::addColumn<int>("errorCode"); |
370 | - QTest::addColumn<QString>("urlResponse"); |
371 | + QTest::addColumn<bool>("uiExpected"); |
372 | QTest::addColumn<QVariantMap>("response"); |
373 | QTest::addColumn<QVariantMap>("stored"); |
374 | |
375 | @@ -304,13 +279,13 @@ |
376 | "ANONYMOUS" << |
377 | userAgentData.toMap() << |
378 | int(Error::MechanismNotAvailable) << |
379 | - QString() << QVariantMap() << QVariantMap(); |
380 | + false << QVariantMap() << QVariantMap(); |
381 | |
382 | QTest::newRow("without params, user_agent") << |
383 | "user_agent" << |
384 | userAgentData.toMap() << |
385 | int(Error::MissingData) << |
386 | - QString() << QVariantMap() << QVariantMap(); |
387 | + false << QVariantMap() << QVariantMap(); |
388 | |
389 | OAuth2PluginData webServerData; |
390 | webServerData.setHost("https://localhost"); |
391 | @@ -324,21 +299,21 @@ |
392 | "web_server" << |
393 | webServerData.toMap() << |
394 | int(Error::MissingData) << |
395 | - QString() << QVariantMap() << QVariantMap(); |
396 | + false << QVariantMap() << QVariantMap(); |
397 | |
398 | userAgentData.setAuthPath("authorize"); |
399 | QTest::newRow("ui-request, user_agent") << |
400 | "user_agent" << |
401 | userAgentData.toMap() << |
402 | -1 << |
403 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
404 | + true << QVariantMap() << QVariantMap(); |
405 | |
406 | webServerData.setTokenPath("token"); |
407 | QTest::newRow("ui-request, web_server") << |
408 | "web_server" << |
409 | webServerData.toMap() << |
410 | -1 << |
411 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
412 | + true << QVariantMap() << QVariantMap(); |
413 | |
414 | QVariantMap tokens; |
415 | QVariantMap token; |
416 | @@ -353,7 +328,7 @@ |
417 | "web_server" << |
418 | webServerData.toMap() << |
419 | -1 << |
420 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
421 | + true << QVariantMap() << QVariantMap(); |
422 | |
423 | tokens.insert(webServerData.ClientId(), QVariant::fromValue(token)); |
424 | webServerData.m_data.insert(QLatin1String("Tokens"), tokens); |
425 | @@ -362,7 +337,7 @@ |
426 | "web_server" << |
427 | webServerData.toMap() << |
428 | -1 << |
429 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
430 | + true << QVariantMap() << QVariantMap(); |
431 | |
432 | token.insert("Scopes", QStringList("scope2")); |
433 | tokens.insert(webServerData.ClientId(), QVariant::fromValue(token)); |
434 | @@ -372,7 +347,7 @@ |
435 | "web_server" << |
436 | webServerData.toMap() << |
437 | -1 << |
438 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
439 | + true << QVariantMap() << QVariantMap(); |
440 | |
441 | token.insert("Scopes", |
442 | QStringList() << "scope1" << "scope3" << "scope2"); |
443 | @@ -386,14 +361,14 @@ |
444 | "web_server" << |
445 | webServerData.toMap() << |
446 | -1 << |
447 | - QString() << response << QVariantMap(); |
448 | + false << response << QVariantMap(); |
449 | |
450 | webServerData.setForceTokenRefresh(true); |
451 | QTest::newRow("force token refresh, without refresh token") << |
452 | "web_server" << |
453 | webServerData.toMap() << |
454 | -1 << |
455 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
456 | + true << QVariantMap() << QVariantMap(); |
457 | |
458 | /* test the ProvidedTokens semantics */ |
459 | OAuth2PluginData providedTokensWebServerData; |
460 | @@ -422,7 +397,7 @@ |
461 | "web_server" << |
462 | providedTokensWebServerData.toMap() << |
463 | -1 << |
464 | - QString() << providedTokens << stored; |
465 | + false << providedTokens << stored; |
466 | } |
467 | |
468 | void OAuth2PluginTest::testPluginProcess() |
469 | @@ -430,27 +405,35 @@ |
470 | QFETCH(QString, mechanism); |
471 | QFETCH(QVariantMap, sessionData); |
472 | QFETCH(int, errorCode); |
473 | - QFETCH(QString, urlResponse); |
474 | + QFETCH(bool, uiExpected); |
475 | QFETCH(QVariantMap, response); |
476 | QFETCH(QVariantMap, stored); |
477 | |
478 | - QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
479 | - this, SLOT(result(const SignOn::SessionData&)),Qt::QueuedConnection); |
480 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
481 | - this, SLOT(pluginError(const SignOn::Error &)),Qt::QueuedConnection); |
482 | - QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
483 | - this, SLOT(uiRequest(const SignOn::UiSessionData&)),Qt::QueuedConnection); |
484 | - QObject::connect(m_testPlugin, SIGNAL(store(const SignOn::SessionData&)), |
485 | - this, SLOT(store(const SignOn::SessionData&)),Qt::QueuedConnection); |
486 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
487 | + QSignalSpy result(m_testPlugin, SIGNAL(result(const SignOn::SessionData&))); |
488 | + QSignalSpy error(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
489 | + QSignalSpy userActionRequired(m_testPlugin, |
490 | + SIGNAL(userActionRequired(const SignOn::UiSessionData&))); |
491 | + QSignalSpy store(m_testPlugin, SIGNAL(store(const SignOn::SessionData&))); |
492 | |
493 | m_testPlugin->process(sessionData, mechanism); |
494 | - m_loop.exec(); |
495 | - QCOMPARE(m_error.type(), errorCode); |
496 | if (errorCode < 0) { |
497 | - QCOMPARE(m_uiResponse.UrlResponse(), urlResponse); |
498 | - QCOMPARE(m_response.toMap(), response); |
499 | - QVERIFY(mapIsSubset(stored, m_stored.toMap())); |
500 | + QCOMPARE(error.count(), 0); |
501 | + QTRY_COMPARE(userActionRequired.count(), uiExpected ? 1 : 0); |
502 | + if (!response.isEmpty()) { |
503 | + QCOMPARE(result.count(), 1); |
504 | + QVariantMap resp = result.at(0).at(0).value<SessionData>().toMap(); |
505 | + QCOMPARE(resp, response); |
506 | + } |
507 | + if (!stored.isEmpty()) { |
508 | + QCOMPARE(store.count(), 1); |
509 | + QVariantMap storedData = |
510 | + store.at(0).at(0).value<SessionData>().toMap(); |
511 | + QVERIFY(mapIsSubset(stored, storedData)); |
512 | + } |
513 | + } else { |
514 | + QTRY_COMPARE(error.count(), 1); |
515 | + Error err = error.at(0).at(0).value<Error>(); |
516 | + QCOMPARE(err.type(), errorCode); |
517 | } |
518 | } |
519 | |
520 | @@ -462,7 +445,7 @@ |
521 | QTest::addColumn<QString>("replyContentType"); |
522 | QTest::addColumn<QString>("replyContents"); |
523 | QTest::addColumn<int>("errorCode"); |
524 | - QTest::addColumn<QString>("urlResponse"); |
525 | + QTest::addColumn<bool>("uiExpected"); |
526 | QTest::addColumn<QVariantMap>("response"); |
527 | QTest::addColumn<QVariantMap>("stored"); |
528 | |
529 | @@ -480,7 +463,7 @@ |
530 | hmacSha1Data.toMap() << |
531 | int(200) << "" << "" << |
532 | int(Error::MechanismNotAvailable) << |
533 | - QString() << QVariantMap() << QVariantMap(); |
534 | + false << QVariantMap() << QVariantMap(); |
535 | |
536 | // Try without params |
537 | hmacSha1Data.setAuthorizationEndpoint(QString()); |
538 | @@ -489,7 +472,7 @@ |
539 | hmacSha1Data.toMap() << |
540 | int(200) << "" << "" << |
541 | int(Error::MissingData) << |
542 | - QString() << QVariantMap() << QVariantMap(); |
543 | + false << QVariantMap() << QVariantMap(); |
544 | |
545 | // Check for signon UI request for HMAC-SHA1 |
546 | hmacSha1Data.setAuthorizationEndpoint("https://localhost/oauth/authorize"); |
547 | @@ -499,7 +482,7 @@ |
548 | int(200) << "text/plain" << |
549 | "oauth_token=HiThere&oauth_token_secret=BigSecret" << |
550 | -1 << |
551 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
552 | + true << QVariantMap() << QVariantMap(); |
553 | |
554 | QTest::newRow("ui-request, PLAINTEXT") << |
555 | "PLAINTEXT" << |
556 | @@ -507,7 +490,7 @@ |
557 | int(200) << "text/plain" << |
558 | "oauth_token=HiThere&oauth_token_secret=BigSecret" << |
559 | -1 << |
560 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
561 | + true << QVariantMap() << QVariantMap(); |
562 | |
563 | /* Now store some tokens and test the responses */ |
564 | hmacSha1Data.m_data.insert("UiPolicy", NoUserInteractionPolicy); |
565 | @@ -527,7 +510,7 @@ |
566 | int(200) << "text/plain" << |
567 | "oauth_token=HiThere&oauth_token_secret=BigSecret" << |
568 | -1 << |
569 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
570 | + true << QVariantMap() << QVariantMap(); |
571 | |
572 | // Ensure that the cached token is returned as required |
573 | tokens.insert(hmacSha1Data.ConsumerKey(), QVariant::fromValue(token)); |
574 | @@ -539,7 +522,7 @@ |
575 | hmacSha1Data.toMap() << |
576 | int(200) << "" << "" << |
577 | -1 << |
578 | - QString() << response << QVariantMap(); |
579 | + false << response << QVariantMap(); |
580 | |
581 | hmacSha1Data.m_data.insert("UiPolicy", RequestPasswordPolicy); |
582 | QTest::newRow("cached tokens, request password policy") << |
583 | @@ -548,7 +531,7 @@ |
584 | int(200) << "text/plain" << |
585 | "oauth_token=HiThere&oauth_token_secret=BigSecret" << |
586 | -1 << |
587 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
588 | + true << QVariantMap() << QVariantMap(); |
589 | hmacSha1Data.m_data.remove("UiPolicy"); |
590 | |
591 | hmacSha1Data.setForceTokenRefresh(true); |
592 | @@ -558,7 +541,7 @@ |
593 | int(200) << "text/plain" << |
594 | "oauth_token=HiThere&oauth_token_secret=BigSecret" << |
595 | -1 << |
596 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
597 | + true << QVariantMap() << QVariantMap(); |
598 | hmacSha1Data.setForceTokenRefresh(false); |
599 | |
600 | token.insert("timestamp", QDateTime::currentDateTime().toTime_t() - 50000); |
601 | @@ -571,7 +554,7 @@ |
602 | int(200) << "text/plain" << |
603 | "oauth_token=HiThere&oauth_token_secret=BigSecret" << |
604 | -1 << |
605 | - QString("UI request received") << QVariantMap() << QVariantMap(); |
606 | + true << QVariantMap() << QVariantMap(); |
607 | |
608 | /* test the ProvidedTokens semantics */ |
609 | OAuth1PluginData providedTokensHmacSha1Data; |
610 | @@ -601,7 +584,7 @@ |
611 | providedTokensHmacSha1Data.toMap() << |
612 | int(200) << "" << "" << |
613 | -1 << |
614 | - QString() << providedTokens << stored; |
615 | + false << providedTokens << stored; |
616 | |
617 | QTest::newRow("http error 401") << |
618 | "HMAC-SHA1" << |
619 | @@ -609,14 +592,14 @@ |
620 | int(401) << "text/plain" << |
621 | "oauth_token=HiThere&oauth_token_secret=BigSecret" << |
622 | int(Error::OperationFailed) << |
623 | - QString() << QVariantMap() << QVariantMap(); |
624 | + false << QVariantMap() << QVariantMap(); |
625 | |
626 | QTest::newRow("no content returned") << |
627 | "HMAC-SHA1" << |
628 | hmacSha1Data.toMap() << |
629 | int(200) << "" << "" << |
630 | int(Error::OperationFailed) << |
631 | - QString() << QVariantMap() << QVariantMap(); |
632 | + false << QVariantMap() << QVariantMap(); |
633 | |
634 | QTest::newRow("no token returned") << |
635 | "HMAC-SHA1" << |
636 | @@ -624,7 +607,7 @@ |
637 | int(200) << "text/plain" << |
638 | "oauth_token=HiThere" << |
639 | int(Error::OperationFailed) << |
640 | - QString() << QVariantMap() << QVariantMap(); |
641 | + false << QVariantMap() << QVariantMap(); |
642 | |
643 | /* Test handling of oauth_problem; this is a non standard extension: |
644 | * http://wiki.oauth.net/w/page/12238543/ProblemReporting |
645 | @@ -636,21 +619,21 @@ |
646 | int(400) << "text/plain" << |
647 | "oauth_problem=user_refused" << |
648 | int(Error::PermissionDenied) << |
649 | - QString() << QVariantMap() << QVariantMap(); |
650 | + false << QVariantMap() << QVariantMap(); |
651 | QTest::newRow("problem permission_denied") << |
652 | "HMAC-SHA1" << |
653 | hmacSha1Data.toMap() << |
654 | int(400) << "text/plain" << |
655 | "oauth_problem=permission_denied" << |
656 | int(Error::PermissionDenied) << |
657 | - QString() << QVariantMap() << QVariantMap(); |
658 | + false << QVariantMap() << QVariantMap(); |
659 | QTest::newRow("problem signature_invalid") << |
660 | "HMAC-SHA1" << |
661 | hmacSha1Data.toMap() << |
662 | int(400) << "text/plain" << |
663 | "oauth_problem=signature_invalid" << |
664 | int(Error::OperationFailed) << |
665 | - QString() << QVariantMap() << QVariantMap(); |
666 | + false << QVariantMap() << QVariantMap(); |
667 | } |
668 | |
669 | void OAuth2PluginTest::testPluginHmacSha1Process() |
670 | @@ -661,19 +644,15 @@ |
671 | QFETCH(QString, replyContentType); |
672 | QFETCH(QString, replyContents); |
673 | QFETCH(int, errorCode); |
674 | - QFETCH(QString, urlResponse); |
675 | + QFETCH(bool, uiExpected); |
676 | QFETCH(QVariantMap, response); |
677 | QFETCH(QVariantMap, stored); |
678 | |
679 | - QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
680 | - this, SLOT(result(const SignOn::SessionData&)),Qt::QueuedConnection); |
681 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
682 | - this, SLOT(pluginError(const SignOn::Error &)),Qt::QueuedConnection); |
683 | - QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
684 | - this, SLOT(uiRequest(const SignOn::UiSessionData&)),Qt::QueuedConnection); |
685 | - QObject::connect(m_testPlugin, SIGNAL(store(const SignOn::SessionData&)), |
686 | - this, SLOT(store(const SignOn::SessionData&)),Qt::QueuedConnection); |
687 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
688 | + QSignalSpy result(m_testPlugin, SIGNAL(result(const SignOn::SessionData&))); |
689 | + QSignalSpy error(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
690 | + QSignalSpy userActionRequired(m_testPlugin, |
691 | + SIGNAL(userActionRequired(const SignOn::UiSessionData&))); |
692 | + QSignalSpy store(m_testPlugin, SIGNAL(store(const SignOn::SessionData&))); |
693 | |
694 | TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
695 | m_testPlugin->m_networkAccessManager = nam; |
696 | @@ -686,13 +665,25 @@ |
697 | nam->setNextReply(reply); |
698 | |
699 | m_testPlugin->process(sessionData, mechanism); |
700 | - m_loop.exec(); |
701 | - QCOMPARE(m_error.type(), errorCode); |
702 | + |
703 | + QTRY_COMPARE(result.count(), response.isEmpty() ? 0 : 1); |
704 | + /* In the test data sometimes we don't specify the expected stored data, |
705 | + * but this doesn't mean that store() shouldn't be emitted. */ |
706 | + if (!stored.isEmpty()) { QTRY_COMPARE(store.count(), 1); } |
707 | + QTRY_COMPARE(userActionRequired.count(), uiExpected ? 1 : 0); |
708 | + QTRY_COMPARE(error.count(), errorCode < 0 ? 0 : 1); |
709 | + |
710 | if (errorCode < 0) { |
711 | + QCOMPARE(error.count(), 0); |
712 | + |
713 | + QVariantMap resp = result.count() > 0 ? |
714 | + result.at(0).at(0).value<SessionData>().toMap() : QVariantMap(); |
715 | + QVariantMap storedData = store.count() > 0 ? |
716 | + store.at(0).at(0).value<SessionData>().toMap() : QVariantMap(); |
717 | /* We don't check the network request if a response was received, |
718 | * because a response can only be received if a cached token was |
719 | * found -- and that doesn't cause any network request to be made. */ |
720 | - if (m_response.toMap().isEmpty()) { |
721 | + if (resp.isEmpty()) { |
722 | QCOMPARE(nam->m_lastRequest.url(), |
723 | sessionData.value("RequestEndpoint").toUrl()); |
724 | QVERIFY(nam->m_lastRequestData.isEmpty()); |
725 | @@ -712,9 +703,11 @@ |
726 | QCOMPARE(authMap.value("oauth_signature_method").toString(), mechanism); |
727 | } |
728 | |
729 | - QCOMPARE(m_uiResponse.UrlResponse(), urlResponse); |
730 | - QVERIFY(mapIsSubset(response, m_response.toMap())); |
731 | - QVERIFY(mapIsSubset(stored, m_stored.toMap())); |
732 | + QVERIFY(mapIsSubset(response, resp)); |
733 | + QVERIFY(mapIsSubset(stored, storedData)); |
734 | + } else { |
735 | + Error err = error.at(0).at(0).value<Error>(); |
736 | + QCOMPARE(err.type(), errorCode); |
737 | } |
738 | } |
739 | |
740 | @@ -731,72 +724,108 @@ |
741 | QStringList scopes = QStringList() << "scope1" << "scope2"; |
742 | data.setScope(scopes); |
743 | |
744 | - QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
745 | - this, SLOT(result(const SignOn::SessionData&)),Qt::QueuedConnection); |
746 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
747 | - this, SLOT(pluginError(const SignOn::Error &)),Qt::QueuedConnection); |
748 | - QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
749 | - this, SLOT(uiRequest(const SignOn::UiSessionData&)),Qt::QueuedConnection); |
750 | - QObject::connect(m_testPlugin, SIGNAL(store(const SignOn::SessionData&)), |
751 | - this, SLOT(store(const SignOn::SessionData&)), |
752 | - Qt::QueuedConnection); |
753 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
754 | + QSignalSpy resultSpy(m_testPlugin, SIGNAL(result(const SignOn::SessionData&))); |
755 | + QSignalSpy error(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
756 | + QSignalSpy userActionRequired(m_testPlugin, |
757 | + SIGNAL(userActionRequired(const SignOn::UiSessionData&))); |
758 | + QSignalSpy store(m_testPlugin, SIGNAL(store(const SignOn::SessionData&))); |
759 | |
760 | m_testPlugin->process(data, QString("user_agent")); |
761 | - m_loop.exec(); |
762 | - QCOMPARE(m_uiResponse.UrlResponse(), QString("UI request received")); |
763 | + |
764 | + QTRY_COMPARE(userActionRequired.count(), 1); |
765 | + QString state = parseState(userActionRequired); |
766 | |
767 | //empty data |
768 | m_testPlugin->userActionFinished(info); |
769 | - m_loop.exec(); |
770 | - QCOMPARE(m_error.type(), int(Error::NotAuthorized)); |
771 | + QTRY_COMPARE(error.count(), 1); |
772 | + QCOMPARE(error.at(0).at(0).value<Error>().type(), int(Error::NotAuthorized)); |
773 | + error.clear(); |
774 | |
775 | //invalid data |
776 | info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html#access_token=&expires_in=4776")); |
777 | m_testPlugin->userActionFinished(info); |
778 | - m_loop.exec(); |
779 | - QCOMPARE(m_error.type(), int(Error::NotAuthorized)); |
780 | + QTRY_COMPARE(error.count(), 1); |
781 | + QCOMPARE(error.at(0).at(0).value<Error>().type(), int(Error::NotAuthorized)); |
782 | + error.clear(); |
783 | |
784 | //Invalid data |
785 | info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html")); |
786 | m_testPlugin->userActionFinished(info); |
787 | - m_loop.exec(); |
788 | - QCOMPARE(m_error.type(), int(Error::NotAuthorized)); |
789 | + QTRY_COMPARE(error.count(), 1); |
790 | + QCOMPARE(error.at(0).at(0).value<Error>().type(), int(Error::NotAuthorized)); |
791 | + error.clear(); |
792 | + |
793 | + // Wrong state |
794 | + info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html" |
795 | + "#access_token=123&expires_in=456&state=%1"). |
796 | + arg(state + "Boo")); |
797 | + m_testPlugin->userActionFinished(info); |
798 | + QTRY_COMPARE(error.count(), 1); |
799 | + QCOMPARE(error.at(0).at(0).value<Error>().type(), int(Error::NotAuthorized)); |
800 | + error.clear(); |
801 | |
802 | //valid data |
803 | - info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html#access_token=testtoken.&expires_in=4776")); |
804 | + info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html#access_token=testtoken.&expires_in=4776&state=%1"). |
805 | + arg(state)); |
806 | m_testPlugin->userActionFinished(info); |
807 | - m_loop.exec(); |
808 | - OAuth2PluginTokenData *result = (OAuth2PluginTokenData*)&m_response; |
809 | - QCOMPARE(result->AccessToken(), QString("testtoken.")); |
810 | - QCOMPARE(result->ExpiresIn(), 4776); |
811 | - QVariantMap storedTokenData = m_stored.data<OAuth2TokenData>().Tokens(); |
812 | + QTRY_COMPARE(resultSpy.count(), 1); |
813 | + SessionData response = resultSpy.at(0).at(0).value<SessionData>(); |
814 | + OAuth2PluginTokenData result = response.data<OAuth2PluginTokenData>(); |
815 | + QCOMPARE(result.AccessToken(), QString("testtoken.")); |
816 | + QCOMPARE(result.ExpiresIn(), 4776); |
817 | + QCOMPARE(result.Scope(), QStringList() << "scope1" << "scope2"); |
818 | + resultSpy.clear(); |
819 | + QTRY_COMPARE(store.count(), 1); |
820 | + SessionData storedData = store.at(0).at(0).value<SessionData>(); |
821 | + QVariantMap storedTokenData = storedData.data<OAuth2TokenData>().Tokens(); |
822 | QVariantMap storedClientData = |
823 | storedTokenData.value(data.ClientId()).toMap(); |
824 | QVERIFY(!storedClientData.isEmpty()); |
825 | QCOMPARE(storedClientData["Scopes"].toStringList(), scopes); |
826 | + store.clear(); |
827 | + |
828 | + //valid data, got scopes |
829 | + info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html#access_token=testtoken.&expires_in=4776&state=%1&scope=scope2"). |
830 | + arg(state)); |
831 | + m_testPlugin->userActionFinished(info); |
832 | + QTRY_COMPARE(resultSpy.count(), 1); |
833 | + response = resultSpy.at(0).at(0).value<SessionData>(); |
834 | + result = response.data<OAuth2PluginTokenData>(); |
835 | + QCOMPARE(result.AccessToken(), QString("testtoken.")); |
836 | + QCOMPARE(result.ExpiresIn(), 4776); |
837 | + QCOMPARE(result.Scope(), QStringList() << "scope2"); |
838 | + resultSpy.clear(); |
839 | + store.clear(); |
840 | |
841 | //valid data |
842 | - info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html#access_token=testtoken.")); |
843 | + info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html" |
844 | + "#state=%1&access_token=testtoken."). |
845 | + arg(state)); |
846 | m_testPlugin->userActionFinished(info); |
847 | - m_loop.exec(); |
848 | - result = (OAuth2PluginTokenData*)&m_response; |
849 | - QCOMPARE(result->AccessToken(), QString("testtoken.")); |
850 | - QCOMPARE(result->ExpiresIn(), 0); |
851 | + QTRY_COMPARE(resultSpy.count(), 1); |
852 | + response = resultSpy.at(0).at(0).value<SessionData>(); |
853 | + result = response.data<OAuth2PluginTokenData>(); |
854 | + QCOMPARE(result.AccessToken(), QString("testtoken.")); |
855 | + QCOMPARE(result.ExpiresIn(), 0); |
856 | + resultSpy.clear(); |
857 | /* Check that the expiration time has not been stored, since the expiration |
858 | * time was not given (https://bugs.launchpad.net/bugs/1316021) |
859 | */ |
860 | - storedTokenData = m_stored.data<OAuth2TokenData>().Tokens(); |
861 | + QTRY_COMPARE(store.count(), 1); |
862 | + storedData = store.at(0).at(0).value<SessionData>(); |
863 | + storedTokenData = storedData.data<OAuth2TokenData>().Tokens(); |
864 | storedClientData = storedTokenData.value(data.ClientId()).toMap(); |
865 | QVERIFY(!storedClientData.isEmpty()); |
866 | QCOMPARE(storedClientData["Token"].toString(), QString("testtoken.")); |
867 | QVERIFY(!storedClientData.contains("Expiry")); |
868 | + store.clear(); |
869 | |
870 | //Permission denied |
871 | info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html?error=user_denied")); |
872 | m_testPlugin->userActionFinished(info); |
873 | - m_loop.exec(); |
874 | - QCOMPARE(m_error.type(), int(Error::NotAuthorized)); |
875 | + QTRY_COMPARE(error.count(), 1); |
876 | + QCOMPARE(error.at(0).at(0).value<Error>().type(), int(Error::NotAuthorized)); |
877 | + error.clear(); |
878 | } |
879 | |
880 | void OAuth2PluginTest::testPluginWebserverUserActionFinished_data() |
881 | @@ -823,7 +852,7 @@ |
882 | "" << "" << 0 << "" << "" << QVariantMap(); |
883 | |
884 | QTest::newRow("permission denied") << |
885 | - "http://localhost/resp.html?error=user_denied" << |
886 | + "http://localhost/resp.html?error=user_denied&$state" << |
887 | int(Error::NotAuthorized) << |
888 | "" << "" << 0 << "" << "" << QVariantMap(); |
889 | |
890 | @@ -833,7 +862,7 @@ |
891 | "" << "" << 0 << "" << "" << QVariantMap(); |
892 | |
893 | QTest::newRow("reply code, http error 401") << |
894 | - "http://localhost/resp.html?code=c0d3" << |
895 | + "http://localhost/resp.html?code=c0d3&$state" << |
896 | int(Error::OperationFailed) << |
897 | "https://localhost/access_token" << |
898 | "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
899 | @@ -843,7 +872,7 @@ |
900 | QVariantMap(); |
901 | |
902 | QTest::newRow("reply code, empty reply") << |
903 | - "http://localhost/resp.html?code=c0d3" << |
904 | + "http://localhost/resp.html?code=c0d3&$state" << |
905 | int(Error::NotAuthorized) << |
906 | "https://localhost/access_token" << |
907 | "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
908 | @@ -853,7 +882,7 @@ |
909 | QVariantMap(); |
910 | |
911 | QTest::newRow("reply code, no access token") << |
912 | - "http://localhost/resp.html?code=c0d3" << |
913 | + "http://localhost/resp.html?code=c0d3&$state" << |
914 | int(Error::NotAuthorized) << |
915 | "https://localhost/access_token" << |
916 | "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
917 | @@ -863,7 +892,7 @@ |
918 | QVariantMap(); |
919 | |
920 | QTest::newRow("reply code, no content type") << |
921 | - "http://localhost/resp.html?code=c0d3" << |
922 | + "http://localhost/resp.html?code=c0d3&$state" << |
923 | int(Error::OperationFailed) << |
924 | "https://localhost/access_token" << |
925 | "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
926 | @@ -873,7 +902,7 @@ |
927 | QVariantMap(); |
928 | |
929 | QTest::newRow("reply code, unsupported content type") << |
930 | - "http://localhost/resp.html?code=c0d3" << |
931 | + "http://localhost/resp.html?code=c0d3&$state" << |
932 | int(Error::OperationFailed) << |
933 | "https://localhost/access_token" << |
934 | "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
935 | @@ -886,19 +915,65 @@ |
936 | response.insert("AccessToken", "t0k3n"); |
937 | response.insert("ExpiresIn", int(3600)); |
938 | response.insert("RefreshToken", QString()); |
939 | - QTest::newRow("reply code, valid token") << |
940 | - "http://localhost/resp.html?code=c0d3" << |
941 | - int(-1) << |
942 | - "https://localhost/access_token" << |
943 | - "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
944 | - int(200) << |
945 | - "application/json" << |
946 | - "{ \"access_token\":\"t0k3n\", \"expires_in\": 3600 }" << |
947 | + QTest::newRow("reply code, valid token, wrong state") << |
948 | + "http://localhost/resp.html?code=c0d3&$wrongstate" << |
949 | + int(Error::NotAuthorized) << |
950 | + "" << |
951 | + "" << |
952 | + int(200) << |
953 | + "application/json" << |
954 | + "{ \"access_token\":\"t0k3n\", \"expires_in\": 3600 }" << |
955 | + response; |
956 | + |
957 | + response.clear(); |
958 | + response.insert("AccessToken", "t0k3n"); |
959 | + response.insert("ExpiresIn", int(3600)); |
960 | + response.insert("RefreshToken", QString()); |
961 | + response.insert("Scope", QStringList() << "one" << "two" << "three"); |
962 | + QTest::newRow("reply code, valid token, no scope") << |
963 | + "http://localhost/resp.html?code=c0d3&$state" << |
964 | + int(-1) << |
965 | + "https://localhost/access_token" << |
966 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
967 | + int(200) << |
968 | + "application/json" << |
969 | + "{ \"access_token\":\"t0k3n\", \"expires_in\": 3600 }" << |
970 | + response; |
971 | + |
972 | + response.clear(); |
973 | + response.insert("AccessToken", "t0k3n"); |
974 | + response.insert("ExpiresIn", int(3600)); |
975 | + response.insert("RefreshToken", QString()); |
976 | + response.insert("Scope", QStringList()); |
977 | + QTest::newRow("reply code, valid token, empty scope") << |
978 | + "http://localhost/resp.html?code=c0d3&$state" << |
979 | + int(-1) << |
980 | + "https://localhost/access_token" << |
981 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
982 | + int(200) << |
983 | + "application/json" << |
984 | + "{ \"access_token\":\"t0k3n\", \"expires_in\": 3600, \"scope\": \"\" }" << |
985 | + response; |
986 | + |
987 | + response.clear(); |
988 | + response.insert("AccessToken", "t0k3n"); |
989 | + response.insert("ExpiresIn", int(3600)); |
990 | + response.insert("RefreshToken", QString()); |
991 | + response.insert("Scope", QStringList() << "one" << "two"); |
992 | + QTest::newRow("reply code, valid token, other scope") << |
993 | + "http://localhost/resp.html?code=c0d3&$state" << |
994 | + int(-1) << |
995 | + "https://localhost/access_token" << |
996 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
997 | + int(200) << |
998 | + "application/json" << |
999 | + "{ \"access_token\":\"t0k3n\", \"expires_in\": 3600, " |
1000 | + "\"scope\": \"one two\" }" << |
1001 | response; |
1002 | |
1003 | response.clear(); |
1004 | QTest::newRow("reply code, facebook, no token") << |
1005 | - "http://localhost/resp.html?code=c0d3" << |
1006 | + "http://localhost/resp.html?code=c0d3&$state" << |
1007 | int(Error::NotAuthorized) << |
1008 | "https://localhost/access_token" << |
1009 | "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
1010 | @@ -911,8 +986,9 @@ |
1011 | response.insert("AccessToken", "t0k3n"); |
1012 | response.insert("ExpiresIn", int(3600)); |
1013 | response.insert("RefreshToken", QString()); |
1014 | + response.insert("Scope", QStringList() << "one" << "two" << "three"); |
1015 | QTest::newRow("reply code, facebook, valid token") << |
1016 | - "http://localhost/resp.html?code=c0d3" << |
1017 | + "http://localhost/resp.html?code=c0d3&$state" << |
1018 | int(-1) << |
1019 | "https://localhost/access_token" << |
1020 | "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
1021 | @@ -925,6 +1001,7 @@ |
1022 | response.insert("AccessToken", "t0k3n"); |
1023 | response.insert("ExpiresIn", int(3600)); |
1024 | response.insert("RefreshToken", QString()); |
1025 | + response.insert("Scope", QStringList() << "one" << "two" << "three"); |
1026 | QTest::newRow("username-password, valid token") << |
1027 | "http://localhost/resp.html?username=us3r&password=s3cr3t" << |
1028 | int(-1) << |
1029 | @@ -939,6 +1016,7 @@ |
1030 | response.insert("AccessToken", "t0k3n"); |
1031 | response.insert("ExpiresIn", int(3600)); |
1032 | response.insert("RefreshToken", QString()); |
1033 | + response.insert("Scope", QStringList() << "one" << "two" << "three"); |
1034 | QTest::newRow("assertion, valid token") << |
1035 | "http://localhost/resp.html?assertion_type=http://oauth.net/token/1.0" |
1036 | "&assertion=oauth1t0k3n" << |
1037 | @@ -954,6 +1032,7 @@ |
1038 | response.insert("AccessToken", "t0k3n"); |
1039 | response.insert("ExpiresIn", int(3600)); |
1040 | response.insert("RefreshToken", QString()); |
1041 | + response.insert("Scope", QStringList() << "one" << "two" << "three"); |
1042 | QTest::newRow("username-password, valid token, wrong content type") << |
1043 | "http://localhost/resp.html?username=us3r&password=s3cr3t" << |
1044 | int(-1) << |
1045 | @@ -984,14 +1063,12 @@ |
1046 | data.setClientId("104660106251471"); |
1047 | data.setClientSecret("fa28f40b5a1f8c1d5628963d880636fbkjkjkj"); |
1048 | data.setRedirectUri("http://localhost/resp.html"); |
1049 | + data.setScope(QStringList() << "one" << "two" << "three"); |
1050 | |
1051 | - QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
1052 | - this, SLOT(result(const SignOn::SessionData&)),Qt::QueuedConnection); |
1053 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
1054 | - this, SLOT(pluginError(const SignOn::Error &)),Qt::QueuedConnection); |
1055 | - QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
1056 | - this, SLOT(uiRequest(const SignOn::UiSessionData&)),Qt::QueuedConnection); |
1057 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
1058 | + QSignalSpy result(m_testPlugin, SIGNAL(result(const SignOn::SessionData&))); |
1059 | + QSignalSpy error(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
1060 | + QSignalSpy userActionRequired(m_testPlugin, |
1061 | + SIGNAL(userActionRequired(const SignOn::UiSessionData&))); |
1062 | |
1063 | TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
1064 | m_testPlugin->m_networkAccessManager = nam; |
1065 | @@ -1004,20 +1081,26 @@ |
1066 | nam->setNextReply(reply); |
1067 | |
1068 | m_testPlugin->process(data, QString("web_server")); |
1069 | - m_loop.exec(); |
1070 | - QCOMPARE(m_uiResponse.UrlResponse(), QString("UI request received")); |
1071 | + QTRY_COMPARE(userActionRequired.count(), 1); |
1072 | + QString state = parseState(userActionRequired); |
1073 | |
1074 | if (!urlResponse.isEmpty()) { |
1075 | + urlResponse.replace("$state", QString("state=") + state); |
1076 | + urlResponse.replace("$wrongstate", QString("state=12") + state); |
1077 | info.setUrlResponse(urlResponse); |
1078 | } |
1079 | |
1080 | m_testPlugin->userActionFinished(info); |
1081 | - m_loop.exec(); |
1082 | |
1083 | - QCOMPARE(m_error.type(), errorCode); |
1084 | + QTRY_COMPARE(error.count(), errorCode < 0 ? 0 : 1); |
1085 | + QTRY_COMPARE(result.count(), errorCode < 0 ? 1 : 0); |
1086 | + if (errorCode >= 0) { |
1087 | + QCOMPARE(error.at(0).at(0).value<Error>().type(), errorCode); |
1088 | + } else { |
1089 | + QCOMPARE(result.at(0).at(0).value<SessionData>().toMap(), response); |
1090 | + } |
1091 | QCOMPARE(nam->m_lastRequest.url(), QUrl(postUrl)); |
1092 | QCOMPARE(QString::fromUtf8(nam->m_lastRequestData), postContents); |
1093 | - QCOMPARE(m_response.toMap(), response); |
1094 | |
1095 | delete nam; |
1096 | } |
1097 | @@ -1132,13 +1215,10 @@ |
1098 | data.setConsumerSecret("fa28f40b5a1f8c1d5628963d880636fbkjkjkj"); |
1099 | data.setRealm("MyHost"); |
1100 | |
1101 | - QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
1102 | - this, SLOT(result(const SignOn::SessionData&)),Qt::QueuedConnection); |
1103 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
1104 | - this, SLOT(pluginError(const SignOn::Error &)),Qt::QueuedConnection); |
1105 | - QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
1106 | - this, SLOT(uiRequest(const SignOn::UiSessionData&)),Qt::QueuedConnection); |
1107 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
1108 | + QSignalSpy result(m_testPlugin, SIGNAL(result(const SignOn::SessionData&))); |
1109 | + QSignalSpy error(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
1110 | + QSignalSpy userActionRequired(m_testPlugin, |
1111 | + SIGNAL(userActionRequired(const SignOn::UiSessionData&))); |
1112 | |
1113 | TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
1114 | m_testPlugin->m_networkAccessManager = nam; |
1115 | @@ -1149,8 +1229,7 @@ |
1116 | nam->setNextReply(reply); |
1117 | |
1118 | m_testPlugin->process(data, mechanism); |
1119 | - m_loop.exec(); |
1120 | - QCOMPARE(m_uiResponse.UrlResponse(), QString("UI request received")); |
1121 | + QTRY_COMPARE(userActionRequired.count(), 1); |
1122 | |
1123 | nam->m_lastRequest = QNetworkRequest(); |
1124 | nam->m_lastRequestData = QByteArray(); |
1125 | @@ -1168,9 +1247,16 @@ |
1126 | } |
1127 | |
1128 | m_testPlugin->userActionFinished(info); |
1129 | - m_loop.exec(); |
1130 | + QTRY_COMPARE(error.count(), errorCode < 0 ? 0 : 1); |
1131 | + QTRY_COMPARE(result.count(), errorCode < 0 ? 1 : 0); |
1132 | + QVariantMap resp; |
1133 | + if (errorCode >= 0) { |
1134 | + QCOMPARE(error.at(0).at(0).value<Error>().type(), errorCode); |
1135 | + } else { |
1136 | + resp = result.at(0).at(0).value<SessionData>().toMap(); |
1137 | + QVERIFY(mapIsSubset(response, resp)); |
1138 | + } |
1139 | |
1140 | - QCOMPARE(m_error.type(), errorCode); |
1141 | if (!expectedAuthMap.isEmpty()) { |
1142 | QCOMPARE(nam->m_lastRequest.url().toString(), data.TokenEndpoint()); |
1143 | QVERIFY(nam->m_lastRequestData.isEmpty()); |
1144 | @@ -1189,9 +1275,6 @@ |
1145 | QCOMPARE(authMap.value("oauth_signature_method").toString(), mechanism); |
1146 | QVERIFY(mapIsSubset(expectedAuthMap, authMap)); |
1147 | } |
1148 | - if (errorCode < 0) { |
1149 | - QVERIFY(mapIsSubset(response, m_response.toMap())); |
1150 | - } |
1151 | |
1152 | delete nam; |
1153 | } |
1154 | @@ -1256,16 +1339,9 @@ |
1155 | data.setClientSecret("fa28f40b5a1f8c1d5628963d880636fbkjkjkj"); |
1156 | data.setRedirectUri("http://localhost/resp.html"); |
1157 | |
1158 | - QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
1159 | - this, SLOT(result(const SignOn::SessionData&)), |
1160 | - Qt::QueuedConnection); |
1161 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
1162 | - this, SLOT(pluginError(const SignOn::Error &)), |
1163 | - Qt::QueuedConnection); |
1164 | - QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
1165 | - this, SLOT(uiRequest(const SignOn::UiSessionData&)), |
1166 | - Qt::QueuedConnection); |
1167 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
1168 | + QSignalSpy error(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
1169 | + QSignalSpy userActionRequired(m_testPlugin, |
1170 | + SIGNAL(userActionRequired(const SignOn::UiSessionData&))); |
1171 | |
1172 | TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
1173 | m_testPlugin->m_networkAccessManager = nam; |
1174 | @@ -1276,13 +1352,14 @@ |
1175 | nam->setNextReply(reply); |
1176 | |
1177 | m_testPlugin->process(data, QString("web_server")); |
1178 | - m_loop.exec(); |
1179 | + QTRY_COMPARE(userActionRequired.count(), 1); |
1180 | + QString state = parseState(userActionRequired); |
1181 | |
1182 | - info.setUrlResponse("http://localhost/resp.html?code=c0d3"); |
1183 | + info.setUrlResponse("http://localhost/resp.html?code=c0d3&state=" + state); |
1184 | m_testPlugin->userActionFinished(info); |
1185 | - m_loop.exec(); |
1186 | |
1187 | - QCOMPARE(m_error.type(), expectedErrorCode); |
1188 | + QTRY_COMPARE(error.count(), 1); |
1189 | + QCOMPARE(error.at(0).at(0).value<Error>().type(), expectedErrorCode); |
1190 | |
1191 | delete nam; |
1192 | } |
1193 | @@ -1313,6 +1390,7 @@ |
1194 | response.insert("AccessToken", "n3w-t0k3n"); |
1195 | response.insert("ExpiresIn", 3600); |
1196 | response.insert("RefreshToken", QString()); |
1197 | + response.insert("Scope", QStringList()); |
1198 | |
1199 | QTest::newRow("expired access token") << data.toMap() << response; |
1200 | |
1201 | @@ -1331,16 +1409,8 @@ |
1202 | |
1203 | SignOn::UiSessionData info; |
1204 | |
1205 | - QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
1206 | - this, SLOT(result(const SignOn::SessionData&)), |
1207 | - Qt::QueuedConnection); |
1208 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
1209 | - this, SLOT(pluginError(const SignOn::Error &)), |
1210 | - Qt::QueuedConnection); |
1211 | - QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
1212 | - this, SLOT(uiRequest(const SignOn::UiSessionData&)), |
1213 | - Qt::QueuedConnection); |
1214 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
1215 | + QSignalSpy result(m_testPlugin, SIGNAL(result(const SignOn::SessionData&))); |
1216 | + QSignalSpy error(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
1217 | |
1218 | TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
1219 | m_testPlugin->m_networkAccessManager = nam; |
1220 | @@ -1351,14 +1421,14 @@ |
1221 | nam->setNextReply(reply); |
1222 | |
1223 | m_testPlugin->process(sessionData, QString("web_server")); |
1224 | - m_loop.exec(); |
1225 | + QTRY_COMPARE(result.count(), 1); |
1226 | + QCOMPARE(error.count(), 0); |
1227 | |
1228 | - QCOMPARE(m_error.type(), -1); |
1229 | QCOMPARE(nam->m_lastRequest.url(), QUrl("https://localhost/access_token")); |
1230 | QCOMPARE(QString::fromUtf8(nam->m_lastRequestData), |
1231 | QString("grant_type=refresh_token&refresh_token=r3fr3sh")); |
1232 | |
1233 | - QCOMPARE(m_response.toMap(), expectedResponse); |
1234 | + QCOMPARE(result.at(0).at(0).value<SessionData>().toMap(), expectedResponse); |
1235 | |
1236 | delete nam; |
1237 | } |
1238 | @@ -1421,16 +1491,9 @@ |
1239 | |
1240 | SignOn::UiSessionData info; |
1241 | |
1242 | - QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
1243 | - this, SLOT(result(const SignOn::SessionData&)), |
1244 | - Qt::QueuedConnection); |
1245 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
1246 | - this, SLOT(pluginError(const SignOn::Error &)), |
1247 | - Qt::QueuedConnection); |
1248 | - QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
1249 | - this, SLOT(uiRequest(const SignOn::UiSessionData&)), |
1250 | - Qt::QueuedConnection); |
1251 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
1252 | + QSignalSpy error(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
1253 | + QSignalSpy userActionRequired(m_testPlugin, |
1254 | + SIGNAL(userActionRequired(const SignOn::UiSessionData&))); |
1255 | |
1256 | TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
1257 | m_testPlugin->m_networkAccessManager = nam; |
1258 | @@ -1445,11 +1508,13 @@ |
1259 | nam->setNextReply(reply); |
1260 | |
1261 | m_testPlugin->process(data, QString("web_server")); |
1262 | - m_loop.exec(); |
1263 | |
1264 | - QCOMPARE(m_error.type(), expectedError); |
1265 | if (expectedError < 0) { |
1266 | - QCOMPARE(m_uiResponse.UrlResponse(), QString("UI request received")); |
1267 | + QTRY_COMPARE(userActionRequired.count(), 1); |
1268 | + QCOMPARE(error.count(), 0); |
1269 | + } else { |
1270 | + QTRY_COMPARE(error.count(), 1); |
1271 | + QCOMPARE(error.at(0).at(0).value<Error>().type(), expectedError); |
1272 | } |
1273 | |
1274 | delete nam; |
1275 | @@ -1502,16 +1567,10 @@ |
1276 | data.setRedirectUri("http://localhost/resp.html"); |
1277 | data.setForceClientAuthViaRequestBody(forceAuthViaRequestBody); |
1278 | |
1279 | - QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
1280 | - this, SLOT(result(const SignOn::SessionData&)), |
1281 | - Qt::QueuedConnection); |
1282 | - QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
1283 | - this, SLOT(pluginError(const SignOn::Error &)), |
1284 | - Qt::QueuedConnection); |
1285 | - QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
1286 | - this, SLOT(uiRequest(const SignOn::UiSessionData&)), |
1287 | - Qt::QueuedConnection); |
1288 | - QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
1289 | + QSignalSpy result(m_testPlugin, SIGNAL(result(const SignOn::SessionData&))); |
1290 | + QSignalSpy error(m_testPlugin, SIGNAL(error(const SignOn::Error &))); |
1291 | + QSignalSpy userActionRequired(m_testPlugin, |
1292 | + SIGNAL(userActionRequired(const SignOn::UiSessionData&))); |
1293 | |
1294 | TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
1295 | m_testPlugin->m_networkAccessManager = nam; |
1296 | @@ -1522,13 +1581,14 @@ |
1297 | nam->setNextReply(reply); |
1298 | |
1299 | m_testPlugin->process(data, QString("web_server")); |
1300 | - m_loop.exec(); |
1301 | + QTRY_COMPARE(userActionRequired.count(), 1); |
1302 | + QString state = parseState(userActionRequired); |
1303 | |
1304 | - info.setUrlResponse("http://localhost/resp.html?code=c0d3"); |
1305 | + info.setUrlResponse("http://localhost/resp.html?code=c0d3&state=" + state); |
1306 | m_testPlugin->userActionFinished(info); |
1307 | - m_loop.exec(); |
1308 | |
1309 | - QCOMPARE(m_error.type(), -1); |
1310 | + QTRY_COMPARE(result.count(), 1); |
1311 | + QCOMPARE(error.count(), 0); |
1312 | QCOMPARE(nam->m_lastRequest.url(), QUrl("https://localhost/access_token")); |
1313 | QCOMPARE(QString::fromUtf8(nam->m_lastRequestData), postContents); |
1314 | QCOMPARE(QString::fromUtf8(nam->m_lastRequest.rawHeader("Authorization")), |
1315 | |
1316 | === modified file 'tests/oauth2plugintest.h' |
1317 | --- tests/oauth2plugintest.h 2015-02-16 12:25:29 +0000 |
1318 | +++ tests/oauth2plugintest.h 2015-04-17 08:14:56 +0000 |
1319 | @@ -35,13 +35,6 @@ |
1320 | { |
1321 | Q_OBJECT |
1322 | |
1323 | -public slots: |
1324 | - void result(const SignOn::SessionData &data); |
1325 | - void pluginError(const SignOn::Error &err); |
1326 | - void uiRequest(const SignOn::UiSessionData &data); |
1327 | - void store(const SignOn::SessionData &data); |
1328 | - void aborted(QNetworkReply *reply); |
1329 | - |
1330 | private slots: |
1331 | void initTestCase(); |
1332 | void cleanupTestCase(); |
1333 | @@ -73,11 +66,6 @@ |
1334 | |
1335 | private: |
1336 | Plugin *m_testPlugin; |
1337 | - SignOn::Error m_error; |
1338 | - SignOn::SessionData m_response; |
1339 | - SignOn::UiSessionData m_uiResponse; |
1340 | - SignOn::SessionData m_stored; |
1341 | - QEventLoop m_loop; |
1342 | }; |
1343 | |
1344 | #endif // OAUTH2PLUGINTEST_H |
1345 | |
1346 | === modified file 'tests/tests.pro' |
1347 | --- tests/tests.pro 2015-01-28 12:09:12 +0000 |
1348 | +++ tests/tests.pro 2015-04-17 08:14:56 +0000 |
1349 | @@ -25,16 +25,9 @@ |
1350 | $${TOP_SRC_DIR}/src \ |
1351 | /usr/include/signon-qt |
1352 | PKGCONFIG += \ |
1353 | + libsignon-qt5 \ |
1354 | signon-plugins |
1355 | |
1356 | -lessThan(QT_MAJOR_VERSION, 5) { |
1357 | - PKGCONFIG += \ |
1358 | - QJson \ |
1359 | - libsignon-qt |
1360 | -} else { |
1361 | - PKGCONFIG += \ |
1362 | - libsignon-qt5 |
1363 | -} |
1364 | |
1365 | target.path = $${INSTALL_PREFIX}/bin |
1366 | testsuite.path = $${INSTALL_PREFIX}/share/$$TARGET |
PASSED: Continuous integration, rev:77 jenkins. qa.ubuntu. com/job/ signon- plugin- oauth2- ci/19/ jenkins. qa.ubuntu. com/job/ signon- plugin- oauth2- vivid-amd64- ci/4 jenkins. qa.ubuntu. com/job/ signon- plugin- oauth2- vivid-armhf- ci/4 jenkins. qa.ubuntu. com/job/ signon- plugin- oauth2- vivid-armhf- ci/4/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ signon- plugin- oauth2- vivid-i386- ci/4
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/signon- plugin- oauth2- ci/19/rebuild
http://