Commit f0ba3c9a authored by Jesus Fernandez's avatar Jesus Fernandez

Added QOAuth1::requestToken

parent 7072c2cf
......@@ -3,4 +3,4 @@ DEPENDPATH += $$OUT_PWD/../QtOAuth
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../QtOAuth/release/ -lQtOAuth
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../QtOAuth/debug/ -lQtOAuth
else:unix: LIBS += -L$$OUT_PWD/../QtOAuth/ -lQtOAuth
else:unix: LIBS += -L$$OUT_PWD/../../QtOAuth/ -lQtOAuth
TEMPLATE = subdirs
SUBDIRS += QtOAuth twittertimeline redditclient
SUBDIRS += \
QtOAuth \
tests \
examples
......@@ -87,8 +87,11 @@ public:
QNetworkAccessManager::Operation operation,
const QVariantMap parameters);
QNetworkReply *requestToken(QNetworkAccessManager::Operation operation, const QUrl &url,
QNetworkReply *requestToken(QNetworkAccessManager::Operation operation,
const QUrl &url,
const QOAuthTokenPair &token,
const QVariantMap &additionalParameters);
QNetworkReply *requestAuthorizationGrant(QNetworkAccessManager::Operation operation,
const QUrl &url,
const QVariantMap &additionalParameters);
......
......@@ -92,8 +92,6 @@ void QOAuth1Private::_q_onTokenRequestFinished()
else {
q->setToken(qMakePair(token, tokenSecret));
q->setStatus(QAbstractOAuth::Status::TokenReceived);
q->postAuthorizationGrant();
}
}
......@@ -187,22 +185,14 @@ void QOAuth1Private::appendSignature(QVariantMap *headers, const QUrl &url,
}
QNetworkReply *QOAuth1Private::requestToken(QNetworkAccessManager::Operation operation,
const QUrl &url, const QVariantMap &parameters)
const QUrl &url,
const QOAuthTokenPair &token,
const QVariantMap &parameters)
{
Q_Q(QOAuth1);
if (q->status() != QAbstractOAuth::Status::NotAuthenticated) {
qWarning("Already authenticated");
return nullptr;
} else if (!networkAccessManager) {
qCritical("QNetworkAccessManager not available");
return nullptr;
}
q->setStatus(QAbstractOAuth::Status::NotAuthenticated);
q->setToken(QOAuthTokenPair());
extraTokens.clear();
Q_EMIT q->extraTokensChanged(extraTokens);
Q_ASSERT(networkAccessManager);
Q_ASSERT(operation == QNetworkAccessManager::GetOperation ||
operation == QNetworkAccessManager::PostOperation);
QNetworkRequest request(url);
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
......@@ -210,6 +200,8 @@ QNetworkReply *QOAuth1Private::requestToken(QNetworkAccessManager::Operation ope
QVariantMap headers;
appendCommonHeaders(&headers);
headers.insert(QStringLiteral("oauth_callback"), q->callback());
if (!token.first.isEmpty())
headers.insert(QStringLiteral("oauth_token"), token.first);
appendSignature(&headers, url, operation, parameters);
request.setRawHeader("Authorization", q->generateAuthorizationHeader(headers));
......@@ -382,6 +374,49 @@ QNetworkReply *QOAuth1::post(const QNetworkRequest &req, const QVariantMap &para
return d->networkAccessManager->post(request, data.toLatin1());
}
QNetworkReply *QOAuth1::requestToken(QNetworkAccessManager::Operation operation,
const QUrl &url,
const QVariantMap &additionalParameters)
{
Q_D(QOAuth1);
if (Q_UNLIKELY(!d->networkAccessManager)) {
qCritical("QNetworkAccessManager not available");
return nullptr;
}
if (Q_UNLIKELY(url.isEmpty())) {
qCritical() << "Request Url not set";
return nullptr;
}
if (Q_UNLIKELY(operation != QNetworkAccessManager::GetOperation &&
operation != QNetworkAccessManager::PostOperation)) {
qCritical("Operation not supported");
return nullptr;
}
return d->requestToken(operation, url, d->token, additionalParameters);
}
QNetworkReply *QOAuth1::requestToken(QNetworkAccessManager::Operation operation,
const QUrl &url,
const QOAuthTokenPair &token,
const QVariantMap &additionalParameters)
{
Q_D(QOAuth1);
if (!d->networkAccessManager) {
qCritical("QNetworkAccessManager not available");
return nullptr;
}
if (Q_UNLIKELY(url.isEmpty())) {
qCritical() << "Request Url not set";
return nullptr;
}
if (Q_UNLIKELY(operation != QNetworkAccessManager::GetOperation &&
operation != QNetworkAccessManager::PostOperation)) {
qCritical("Operation not supported");
return nullptr;
}
return d->requestToken(operation, url, token, additionalParameters);
}
void QOAuth1::setup(QNetworkRequest *request, const QVariantMap &signingParameters,
QNetworkAccessManager::Operation operation)
{
......@@ -551,10 +586,13 @@ void QOAuth1::grant()
if (d->status == Status::NotAuthenticated) {
d->setStatus(Status::TokenReceived);
postAuthorizationGrant();
requestToken(QNetworkAccessManager::PostOperation, authorizationGrantUrl());
} else if (d->status == Status::TokenReceived) {
d->setStatus(Status::Authenticated);
Q_EMIT granted();
}
});
postRequestToken(extraTokens());
requestToken(QNetworkAccessManager::PostOperation, requestTokenUrl(), QOAuthTokenPair());
}
void QOAuth1::setExtraTokens(const QVariantMap &tokens)
......@@ -563,56 +601,6 @@ void QOAuth1::setExtraTokens(const QVariantMap &tokens)
d->extraTokens = tokens;
}
QNetworkReply * QOAuth1::getRequestToken(const QVariantMap &parameters)
{
Q_D(QOAuth1);
if (!d->networkAccessManager) {
qCritical("QNetworkAccessManager not available");
return nullptr;
}
if (Q_UNLIKELY(requestTokenUrl().isEmpty())) {
qCritical() << "Request Url not set";
return nullptr;
}
return d->requestToken(QNetworkAccessManager::GetOperation, requestTokenUrl(),
parameters);
}
QNetworkReply * QOAuth1::postRequestToken(const QVariantMap &parameters)
{
Q_D(QOAuth1);
if (Q_UNLIKELY(d->requestTokenUrl.isEmpty())) {
qCritical("Request Url not set");
return nullptr;
}
return d->requestToken(QNetworkAccessManager::PostOperation, d->requestTokenUrl,
parameters);
}
QNetworkReply * QOAuth1::getAuthorizationGrant(const QVariantMap &parameters)
{
Q_D(QOAuth1);
if (Q_UNLIKELY(d->authorizationGrantUrl.isEmpty())) {
qCritical("Authorization grant Url not set");
return nullptr;
}
return d->requestAuthorizationGrant(QNetworkAccessManager::GetOperation,
d->authorizationGrantUrl,
parameters);
}
QNetworkReply * QOAuth1::postAuthorizationGrant(const QVariantMap &parameters)
{
Q_D(QOAuth1);
if (Q_UNLIKELY(d->authorizationGrantUrl.isEmpty())) {
qCritical("Authorization grant Url not set");
return nullptr;
}
return d->requestAuthorizationGrant(QNetworkAccessManager::PostOperation,
d->authorizationGrantUrl,
parameters);
}
QT_END_NAMESPACE
#endif // QT_NO_HTTP
......@@ -50,7 +50,9 @@ class QOAuth1Private;
class Q_NETWORK_EXPORT QOAuth1: public QAbstractOAuth
{
Q_OBJECT
Q_PROPERTY(SignatureMethod signatureMethod READ signatureMethod WRITE setSignatureMethod
Q_PROPERTY(SignatureMethod signatureMethod
READ signatureMethod
WRITE setSignatureMethod
NOTIFY signatureMethodChanged)
public:
......@@ -68,6 +70,15 @@ public:
virtual QNetworkReply *post(const QNetworkRequest &req,
const QVariantMap &parameters = QVariantMap()) override;
QNetworkReply *requestToken(QNetworkAccessManager::Operation operation,
const QUrl &url,
const QVariantMap &additionalParameters = QVariantMap());
QNetworkReply *requestToken(QNetworkAccessManager::Operation operation,
const QUrl &url,
const QOAuthTokenPair &token,
const QVariantMap &additionalParameters = QVariantMap());
virtual void grant() override;
Q_SIGNALS:
......@@ -76,12 +87,6 @@ Q_SIGNALS:
protected:
void setExtraTokens(const QVariantMap &tokens);
virtual QNetworkReply *getRequestToken(const QVariantMap &parameters = QVariantMap());
virtual QNetworkReply *postRequestToken(const QVariantMap &parameters = QVariantMap());
virtual QNetworkReply *getAuthorizationGrant(const QVariantMap &parameters = QVariantMap());
virtual QNetworkReply *postAuthorizationGrant(const QVariantMap &parameters = QVariantMap());
void setup(QNetworkRequest *request,
const QVariantMap &signingParameters,
QNetworkAccessManager::Operation operation);
......
TEMPLATE = subdirs
SUBDIRS += \
twittertimeline \
redditclient
......@@ -13,4 +13,4 @@ HEADERS += \
FORMS +=
include(../QtOAuth.pri)
include(../../QtOAuth.pri)
......@@ -18,5 +18,5 @@ INSTALLS += target
FORMS += \
twitterdialog.ui
include(../QtOAuth.pri)
include(../../QtOAuth.pri)
CONFIG += testcase
TARGET = tst_qoauth
SOURCES += tst_qoauth.cpp
INCLUDEPATH += /
QT = core core-private network testlib
include(../../QtOAuth.pri)
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore>
#include <QtTest>
#include <QtNetwork>
#include <qoauth1.h>
#include <qabstractoauth.h>
#include <private/qoauth1_p.h>
#include <private/qabstractoauth_p.h>
Q_DECLARE_METATYPE(QNetworkAccessManager::Operation)
Q_DECLARE_METATYPE(QAbstractOAuth::Error)
typedef QSharedPointer<QNetworkReply> QNetworkReplyPtr;
class tst_QOAuth: public QObject
{
Q_OBJECT
QEventLoop *loop;
enum RunSimpleRequestReturn { Timeout = 0, Success, Failure };
int returnCode;
using QObject::connect;
static bool connect(const QNetworkReplyPtr &ptr, const char *signal, const QObject *receiver, const char *slot, Qt::ConnectionType ct = Qt::AutoConnection)
{ return connect(ptr.data(), signal, receiver, slot, ct); }
bool connect(const QNetworkReplyPtr &ptr, const char *signal, const char *slot, Qt::ConnectionType ct = Qt::AutoConnection)
{ return connect(ptr.data(), signal, slot, ct); }
public:
int waitForFinish(QNetworkReplyPtr &reply);
void test_data();
void fillParameters(QVariantMap *parameters, const QUrlQuery &query);
public Q_SLOTS:
void finished();
void gotError();
private Q_SLOTS:
void createSignature();
void getToken_data();
void getToken();
void grant_data();
void grant();
void authenticatedCalls_data();
void authenticatedCalls();
};
int tst_QOAuth::waitForFinish(QNetworkReplyPtr &reply)
{
int count = 0;
connect(reply, SIGNAL(finished()), SLOT(finished()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError()));
returnCode = Success;
loop = new QEventLoop;
QSignalSpy spy(reply.data(), SIGNAL(downloadProgress(qint64,qint64)));
while (!reply->isFinished()) {
QTimer::singleShot(5000, loop, SLOT(quit()));
if ( loop->exec() == Timeout && count == spy.count() && !reply->isFinished()) {
returnCode = Timeout;
break;
}
count = spy.count();
}
delete loop;
loop = 0;
return returnCode;
}
void tst_QOAuth::test_data()
{
QTest::addColumn<QString>("consumerKey");
QTest::addColumn<QString>("consumerSecret");
QTest::addColumn<QString>("requestToken");
QTest::addColumn<QString>("requestTokenSecret");
QTest::addColumn<QString>("accessToken");
QTest::addColumn<QString>("accessTokenSecret");
QTest::addColumn<QUrl>("requestTokenUrl");
QTest::addColumn<QUrl>("accessTokenUrl");
QTest::addColumn<QUrl>("authenticatedCallUrl");
QTest::addColumn<QNetworkAccessManager::Operation>("requestType");
QTest::newRow("term.ie_get") << "key"
<< "secret"
<< "requestkey"
<< "requestsecret"
<< "accesskey"
<< "accesssecret"
<< QUrl("http://term.ie/oauth/example/request_token.php")
<< QUrl("http://term.ie/oauth/example/access_token.php")
<< QUrl("http://term.ie/oauth/example/echo_api.php")
<< QNetworkAccessManager::GetOperation;
QTest::newRow("term.ie_post") << "key"
<< "secret"
<< "requestkey"
<< "requestsecret"
<< "accesskey"
<< "accesssecret"
<< QUrl("http://term.ie/oauth/example/request_token.php")
<< QUrl("http://term.ie/oauth/example/access_token.php")
<< QUrl("http://term.ie/oauth/example/echo_api.php")
<< QNetworkAccessManager::PostOperation;
QTest::newRow("oauthbin.com_get") << "key"
<< "secret"
<< "requestkey"
<< "requestsecret"
<< "accesskey"
<< "accesssecret"
<< QUrl("http://oauthbin.com/v1/request-token")
<< QUrl("http://oauthbin.com/v1/access-token")
<< QUrl("http://oauthbin.com/v1/echo")
<< QNetworkAccessManager::GetOperation;
QTest::newRow("oauthbin.com_post") << "key"
<< "secret"
<< "requestkey"
<< "requestsecret"
<< "accesskey"
<< "accesssecret"
<< QUrl("http://oauthbin.com/v1/request-token")
<< QUrl("http://oauthbin.com/v1/access-token")
<< QUrl("http://oauthbin.com/v1/echo")
<< QNetworkAccessManager::PostOperation;
}
void tst_QOAuth::fillParameters(QVariantMap *parameters, const QUrlQuery &query)
{
const auto list = query.queryItems();
for (auto it = list.begin(), end = list.end(); it != end; ++it)
parameters->insert(it->first, it->second);
}
void tst_QOAuth::finished()
{
loop->exit(returnCode = Success);
}
void tst_QOAuth::gotError()
{
loop->exit(returnCode = Failure);
disconnect(QObject::sender(), SIGNAL(finished()), this, 0);
}
void tst_QOAuth::createSignature()
{
// Example from https://dev.twitter.com/oauth/overview/creating-signatures
QByteArray parameterString, signatureBase, signature;
const QUrl url(QStringLiteral(
"https://api.twitter.com/1/statuses/update.json?include_entities=true"));
const QString data = QUrl::fromPercentEncoding("status=Hello%20Ladies%20%2b%20Gentlemen%2c%20a%20signed%20OAuth%20request%21");
const auto consumerSecret = QStringLiteral("kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw");
const auto oauthTokenSecret = QStringLiteral("LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE");
QNetworkAccessManager::Operation operation = QNetworkAccessManager::PostOperation;
QVariantMap oauthParams;
oauthParams.insert(QStringLiteral("oauth_consumer_key"),
QStringLiteral("xvz1evFS4wEEPTGEFPHBog"));
oauthParams.insert(QStringLiteral("oauth_nonce"),
QStringLiteral("kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg"));
oauthParams.insert(QStringLiteral("oauth_signature_method"),
QStringLiteral("HMAC-SHA1"));
oauthParams.insert(QStringLiteral("oauth_timestamp"), QStringLiteral("1318622958"));
oauthParams.insert(QStringLiteral("oauth_token"),
QStringLiteral("370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb"));
oauthParams.insert(QStringLiteral("oauth_version"), QStringLiteral("1.0"));
QVariantMap otherParametersFromData;
fillParameters(&otherParametersFromData, QUrlQuery(data));
// HTTP Method
QCOMPARE(QOAuth1Private::operationName(operation), QStringLiteral("POST"));
// Base URL
QCOMPARE(url.toString(QUrl::RemoveQuery),
QStringLiteral("https://api.twitter.com/1/statuses/update.json"));
struct OAuthSubClass : QOAuth1 {
using QOAuth1::parameterString;
using QOAuth1::signatureBase;
using QOAuth1::sign;
};
// Creating parameter string
{
QVariantMap parameters = oauthParams;
parameters.unite(otherParametersFromData);
fillParameters(&parameters, QUrlQuery(url.query()));
parameterString = OAuthSubClass::parameterString(parameters);
parameters.insertMulti(parameters.keys().first(), QString());
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("^QOAuth: duplicated key .*$"));
OAuthSubClass::parameterString(parameters);
}
QCOMPARE(parameterString, QByteArray("include_entities=true"
"&oauth_consumer_key=xvz1evFS4wEEPTGEFPHBog"
"&oauth_nonce=kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg"
"&oauth_signature_method=HMAC-SHA1"
"&oauth_timestamp=1318622958"
"&oauth_token=370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb"
"&oauth_version=1.0"
"&status=Hello%20Ladies%20%2B%20Gentlemen%2C%20a%20signed%20OAuth%20request%21"));
// Collecting parameters
oauthParams.unite(otherParametersFromData);
signatureBase = OAuthSubClass::signatureBase(oauthParams, url, operation);
QCOMPARE(signatureBase, QByteArray("POST&https%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json"
"&include_entities%3Dtrue%26oauth_consumer_key%3Dxvz1evFS4wEEPTGEFPHBog"
"%26oauth_nonce%3DkYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg"
"%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1318622958"
"%26oauth_token%3D370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb"
"%26oauth_version%3D1.0%26status%3DHello%2520Ladies%2520%252B%2520Gentlemen%252C%2520a%2520signed%2520OAuth%2520request%2521"));
// Getting a signing key
signature = OAuthSubClass::sign(oauthParams, url, operation, consumerSecret, oauthTokenSecret);
QCOMPARE(signature, QByteArray("tnnArxj06cWHq44gCs1OSKk/jLY="));
}
void tst_QOAuth::getToken_data()
{
QTest::addColumn<QOAuthTokenPair>("key");
QTest::addColumn<QOAuthTokenPair>("token");
QTest::addColumn<QOAuthTokenPair>("expectedToken");
QTest::addColumn<QUrl>("url");
QTest::addColumn<QNetworkAccessManager::Operation>("requestType");
// term.ie
QTest::newRow("term.ie_request_get") << qMakePair(QStringLiteral("key"),
QStringLiteral("secret"))
<< qMakePair(QStringLiteral(),
QStringLiteral())
<< qMakePair(QStringLiteral("requestkey"),
QStringLiteral("requestsecret"))
<< QUrl("http://term.ie/oauth/example/request_token.php")
<< QNetworkAccessManager::GetOperation;
QTest::newRow("term.ie_request_post") << qMakePair(QStringLiteral("key"),
QStringLiteral("secret"))
<< qMakePair(QStringLiteral(),
QStringLiteral())
<< qMakePair(QStringLiteral("requestkey"),
QStringLiteral("requestsecret"))
<< QUrl("http://term.ie/oauth/example/request_token.php")
<< QNetworkAccessManager::PostOperation;
QTest::newRow("term.ie_access_get") << qMakePair(QStringLiteral("key"),
QStringLiteral("secret"))
<< qMakePair(QStringLiteral("requestkey"),
QStringLiteral("requestsecret"))
<< qMakePair(QStringLiteral("accesskey"),
QStringLiteral("accesssecret"))
<< QUrl("http://term.ie/oauth/example/access_token.php")
<< QNetworkAccessManager::GetOperation;
QTest::newRow("term.ie_access_post") << qMakePair(QStringLiteral("key"),
QStringLiteral("secret"))
<< qMakePair(QStringLiteral("requestkey"),
QStringLiteral("requestsecret"))
<< qMakePair(QStringLiteral("accesskey"),
QStringLiteral("accesssecret"))
<< QUrl("http://term.ie/oauth/example/access_token.php")
<< QNetworkAccessManager::PostOperation;
// oauthbin.com
QTest::newRow("oauthbin.com_request_get") << qMakePair(QStringLiteral("key"),
QStringLiteral("secret"))
<< qMakePair(QStringLiteral(),
QStringLiteral())
<< qMakePair(QStringLiteral("requestkey"),
QStringLiteral("requestsecret"))
<< QUrl("http://oauthbin.com/v1/request-token")
<< QNetworkAccessManager::GetOperation;
QTest::newRow("oauthbin.com_request_post") << qMakePair(QStringLiteral("key"),
QStringLiteral("secret"))
<< qMakePair(QStringLiteral(),
QStringLiteral())
<< qMakePair(QStringLiteral("requestkey"),
QStringLiteral("requestsecret"))
<< QUrl("http://oauthbin.com/v1/request-token")
<< QNetworkAccessManager::PostOperation;
QTest::newRow("oauthbin.com_access_get") << qMakePair(QStringLiteral("key"),
QStringLiteral("secret"))
<< qMakePair(QStringLiteral("requestkey"),
QStringLiteral("requestsecret"))
<< qMakePair(QStringLiteral("accesskey"),
QStringLiteral("accesssecret"))
<< QUrl("http://oauthbin.com/v1/access-token")
<< QNetworkAccessManager::GetOperation;
QTest::newRow("oauthbin.com_access_post") << qMakePair(QStringLiteral("key"),
QStringLiteral("secret"))
<< qMakePair(QStringLiteral("requestkey"),
QStringLiteral("requestsecret"))
<< qMakePair(QStringLiteral("accesskey"),
QStringLiteral("accesssecret"))
<< QUrl("http://oauthbin.com/v1/access-token")
<< QNetworkAccessManager::PostOperation;
}
void tst_QOAuth::getToken()
{
QFETCH(QOAuthTokenPair, key);
QFETCH(QOAuthTokenPair, token);
QFETCH(QOAuthTokenPair, expectedToken);
QFETCH(QUrl, url);
QFETCH(QNetworkAccessManager::Operation, requestType);
QOAuthTokenPair tokenReceived;
QNetworkAccessManager networkAccessManager;
QNetworkReplyPtr reply;
QOAuth1 o1(&networkAccessManager);
o1.setClientId(key);
o1.setToken(token);
o1.setRequestTokenUrl(url);
reply.reset(o1.requestToken(requestType, url));
QVERIFY(!reply.isNull());
connect(&o1, &QAbstractOAuth::tokenChanged, [&tokenReceived](
const QOAuthTokenPair &token){
tokenReceived = token;
});
QVERIFY(waitForFinish(reply) == Success);
QVERIFY(!tokenReceived.first.isEmpty() && !tokenReceived.second.isEmpty());
}
void tst_QOAuth::grant_data()
{
test_data();
}
void tst_QOAuth::grant()
{
QFETCH(QString, consumerKey);
QFETCH(QString, consumerSecret);
QFETCH(QString, requestToken);
QFETCH(QString, requestTokenSecret);
QFETCH(QString, accessToken);
QFETCH(QString, accessTokenSecret);
QFETCH(QUrl, requestTokenUrl);
QFETCH(QUrl, accessTokenUrl);
bool tokenReceived = false;
QNetworkAccessManager networkAccessManager;
QOAuth1 o1(&networkAccessManager);
{
QSignalSpy spy(&o1, &QAbstractOAuth::requestTokenUrlChanged);
o1.setRequestTokenUrl(requestTokenUrl);
QCOMPARE(spy.count(), 1);
<