summaryrefslogtreecommitdiffstats
path: root/tests/auto/network/access
diff options
context:
space:
mode:
authorJuha Vuolle <juha.vuolle@qt.io>2024-01-19 11:33:39 +0200
committerJuha Vuolle <juha.vuolle@qt.io>2024-01-29 19:02:37 +0200
commit9ba5c7ff6aa42c5701cf950d2137467a2d178833 (patch)
tree59e5116c50e9a314cbec4a68267f719846f14e01 /tests/auto/network/access
parentbe6c651be4ccfa4f70009bcbb51bef39638e0fba (diff)
Make QRest* APIs non-owning and non-duplicating
Note: documentation will be updated in a follow-up commit This commit makes QRestReply and QRestAccessManager classes lighter, non-owning wrappers. Furthermore their APIs don't duplicate the wrapped QNetwork* APIs. This makes it easier to use / opt-in to these helpers in pre-existing applications which are based on QNetworkAccessManager and QNetworkReply. Since APIs are no longer duplicated, the QRest classes are more obviously a convenience _wrapper_, as opposed to being an alternative vertical stack. In practice this change consists of: - QRestAM never instantiates QNetworkAccessManager, but accepts it via constructor. It does not take ownership of the QNetworkAccessManager. - QRestReply accepts QNetworkReply via constructor. It does not take ownership of the QNetworkReply - Signals and most duplicated functions are removed from both QRestAM and QRR. - QRestReply is no longer a QObject - Since QRestAM doesn't have much to report anymore, the debug operator is dropped. Resulted from API-review Pick-to: 6.7 Change-Id: Ib62d9cc2df41cac631396a84bb7ec4d2d54b0c8c Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Diffstat (limited to 'tests/auto/network/access')
-rw-r--r--tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp858
1 files changed, 305 insertions, 553 deletions
diff --git a/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp b/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp
index d1018952bd..890b7609e1 100644
--- a/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp
+++ b/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp
@@ -29,63 +29,76 @@ class tst_QRestAccessManager : public QObject
Q_OBJECT
private slots:
- void initTestCase();
-
void initialization();
void destruction();
void callbacks();
- void threading();
- void networkRequestReply();
- void abort();
- void authentication();
- void userInfo();
+ void requests();
+ void reply();
void errors();
void body();
void json();
void text();
void textStreaming();
- void download();
- void upload();
- void timeout();
private:
- void memberHandler(QRestReply *reply);
+ void memberHandler(QRestReply &reply);
friend class Transient;
- QList<QRestReply*> m_expectedReplies;
- QList<QRestReply*> m_actualReplies;
+ QList<QNetworkReply*> m_expectedReplies;
+ QList<QNetworkReply*> m_actualReplies;
};
-void tst_QRestAccessManager::initTestCase()
+void tst_QRestAccessManager::initialization()
{
- qRegisterMetaType<QRestReply*>(); // For QSignalSpy
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QRestAccessManager: QNetworkAccesManager is nullptr");
+ QRestAccessManager manager1(nullptr);
+ QVERIFY(!manager1.networkAccessManager());
+
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager2(&qnam);
+ QVERIFY(manager2.networkAccessManager());
}
-void tst_QRestAccessManager::initialization()
+void tst_QRestAccessManager::reply()
{
- QRestAccessManager manager;
- QVERIFY(manager.networkAccessManager());
- QCOMPARE(manager.deletesRepliesOnFinished(), true);
+ QNetworkAccessManager qnam;
+
+ QNetworkReply *nr = qnam.get(QNetworkRequest(QUrl{"someurl"}));
+ QRestReply rr1(nr);
+ QCOMPARE(rr1.networkReply(), nr);
+
+ // Move-construct
+ QRestReply rr2(std::move(rr1));
+ QCOMPARE(rr2.networkReply(), nr);
+
+ // Move-assign
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QRestReply: QNetworkReply is nullptr");
+ QRestReply rr3(nullptr);
+ rr3 = std::move(rr2);
+ QCOMPARE(rr3.networkReply(), nr);
}
-#define VERIFY_REPLY_OK(METHOD) \
- QTRY_VERIFY(replyFromServer); \
+#define VERIFY_REPLY_OK(METHOD) \
+{ \
+ QTRY_VERIFY(networkReply); \
+ QRestReply restReply(networkReply); \
QCOMPARE(serverSideRequest.method, METHOD); \
- QVERIFY(replyFromServer->isSuccess()); \
- QVERIFY(!replyFromServer->hasError()); \
- replyFromServer->deleteLater(); \
- replyFromServer = nullptr; \
+ QVERIFY(restReply.isSuccess()); \
+ QVERIFY(!restReply.hasError()); \
+ networkReply->deleteLater(); \
+ networkReply = nullptr; \
+}
-void tst_QRestAccessManager::networkRequestReply()
+void tst_QRestAccessManager::requests()
{
// A basic test for each HTTP method against the local testserver.
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
HttpTestServer server;
QTRY_VERIFY(server.isListening());
QNetworkRequest request(server.url());
request.setRawHeader("Content-Type"_ba, "text/plain"); // To silence missing content-type warn
- QRestReply *replyFromServer = nullptr;
+ QNetworkReply *networkReply = nullptr;
std::unique_ptr<QHttpMultiPart> multiPart;
QHttpPart part;
part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));
@@ -101,7 +114,7 @@ void tst_QRestAccessManager::networkRequestReply()
response = serverSideResponse;
});
- auto callback = [&](QRestReply *reply) { replyFromServer = reply; };
+ auto callback = [&](QRestReply &reply) { networkReply = reply.networkReply(); };
const QByteArray byteArrayData{"some_data"_ba};
const QJsonObject jsonObjectData{{"key1", "value1"}, {"key2", "value2"}};
const QJsonArray jsonArrayData{{"arrvalue1", "arrvalue2", QJsonObject{{"key1", "value1"}}}};
@@ -255,44 +268,9 @@ void tst_QRestAccessManager::networkRequestReply()
//manager.sendCustomRequest(request, "FOOBAR", this, [](){}); // No verb || no data
}
-void tst_QRestAccessManager::abort()
+void tst_QRestAccessManager::memberHandler(QRestReply &reply)
{
- // Test aborting requests
- QRestAccessManager manager;
- HttpTestServer server;
- QTRY_VERIFY(server.isListening());
- QNetworkRequest request(server.url());
-
- QSignalSpy finishedSpy(&manager, &QRestAccessManager::requestFinished);
- int callbackCount = 0;
- auto callback = [&](QRestReply*) {
- callbackCount++;
- };
-
- // Abort without any requests
- manager.abortRequests();
- QTest::qWait(20);
- QCOMPARE(finishedSpy.size(), 0);
-
- // Abort immediately after requesting
- manager.get(request, this, callback);
- manager.abortRequests();
- QTRY_COMPARE(callbackCount, 1);
- QTRY_COMPARE(finishedSpy.size(), 1);
-
- // Abort after request has been sent out
- server.setHandler([&](HttpData, HttpData&, ResponseControl &control) {
- control.respond = false;
- manager.abortRequests();
- });
- manager.get(request, this, callback);
- QTRY_COMPARE(callbackCount, 2);
- QTRY_COMPARE(finishedSpy.size(), 2);
-}
-
-void tst_QRestAccessManager::memberHandler(QRestReply *reply)
-{
- m_actualReplies.append(reply);
+ m_actualReplies.append(reply.networkReply());
}
// Class that is destroyed during an active request.
@@ -303,9 +281,9 @@ class Transient : public QObject
public:
explicit Transient(tst_QRestAccessManager *test) : QObject(test), m_test(test) {}
- void memberHandler(QRestReply *reply)
+ void memberHandler(QRestReply &reply)
{
- m_test->m_actualReplies.append(reply);
+ m_test->m_actualReplies.append(reply.networkReply());
}
private:
@@ -313,53 +291,51 @@ private:
};
template <typename Functor, std::enable_if_t<
- QtPrivate::AreFunctionsCompatible<void(*)(QRestReply*), Functor>::value, bool> = true>
+ QtPrivate::AreFunctionsCompatible<void(*)(QRestReply&), Functor>::value, bool> = true>
inline constexpr bool isCompatibleCallback(Functor &&) { return true; }
template <typename Functor, std::enable_if_t<
- !QtPrivate::AreFunctionsCompatible<void(*)(QRestReply*), Functor>::value, bool> = true,
+ !QtPrivate::AreFunctionsCompatible<void(*)(QRestReply&), Functor>::value, bool> = true,
typename = void>
inline constexpr bool isCompatibleCallback(Functor &&) { return false; }
void tst_QRestAccessManager::callbacks()
{
- QRestAccessManager manager;
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
- manager.setDeletesRepliesOnFinished(false); // Don't autodelete so we can compare results later
QNetworkRequest request{u"i_dont_exist"_s}; // Will result in ProtocolUnknown error
- QSignalSpy managerFinishedSpy(&manager, &QRestAccessManager::requestFinished);
- auto lambdaHandler = [this](QRestReply *reply) { m_actualReplies.append(reply); };
- QRestReply *reply = nullptr;
+ auto lambdaHandler = [this](QRestReply &reply) { m_actualReplies.append(reply.networkReply()); };
Transient *transient = nullptr;
QByteArray data{"some_data"};
// Compile-time tests for callback signatures
- static_assert(isCompatibleCallback([](QRestReply*){})); // Correct signature
+ static_assert(isCompatibleCallback([](QRestReply&){})); // Correct signature
static_assert(isCompatibleCallback(lambdaHandler));
static_assert(isCompatibleCallback(&Transient::memberHandler));
static_assert(isCompatibleCallback([](){})); // Less parameters are allowed
- static_assert(!isCompatibleCallback([](QString){})); // Wrong parameter type
- static_assert(!isCompatibleCallback([](QNetworkReply*){})); // Wrong parameter type
- static_assert(!isCompatibleCallback([](const QString &){})); // Wrong parameter type
- static_assert(!isCompatibleCallback([](QRestReply*, QString){})); // Too many parameters
+ static_assert(!isCompatibleCallback([](QString){})); // Wrong parameter type
+ static_assert(!isCompatibleCallback([](QRestReply*){})); // Wrong parameter type
+ static_assert(!isCompatibleCallback([](const QString &){})); // Wrong parameter type
+ static_assert(!isCompatibleCallback([](QRestReply&, QString){})); // Too many parameters
// -- Test without data
- // Without callback
- reply = manager.get(request);
- QCOMPARE(reply->isFinished(), false); // Test this once here
+ // Without callback using signals and slot
+ QNetworkReply* reply = manager.get(request);
m_expectedReplies.append(reply);
- QObject::connect(reply, &QRestReply::finished, lambdaHandler);
+ QObject::connect(reply, &QNetworkReply::finished, this,
+ [this, reply](){m_actualReplies.append(reply);});
// With lambda callback, without context object
m_expectedReplies.append(manager.get(request, nullptr, lambdaHandler));
m_expectedReplies.append(manager.get(request, nullptr,
- [this](QRestReply *reply){m_actualReplies.append(reply);}));
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
// With lambda callback and context object
m_expectedReplies.append(manager.get(request, this, lambdaHandler));
m_expectedReplies.append(manager.get(request, this,
- [this](QRestReply *reply){m_actualReplies.append(reply);}));
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
// With member callback and context object
m_expectedReplies.append(manager.get(request, this, &tst_QRestAccessManager::memberHandler));
// With context object that is destroyed, there should be no callback or eg. crash.
@@ -369,31 +345,26 @@ void tst_QRestAccessManager::callbacks()
// Let requests finish
QTRY_COMPARE(m_actualReplies.size(), m_expectedReplies.size());
- QTRY_COMPARE(managerFinishedSpy.size(), m_actualReplies.size());
for (auto reply: m_actualReplies) {
- QVERIFY(!reply->isSuccess());
- QVERIFY(reply->hasError());
- QCOMPARE(reply->error(), QNetworkReply::ProtocolUnknownError);
- QCOMPARE(reply->isFinished(), true);
- reply->deleteLater();
+ QRestReply restReply(reply);
+ QVERIFY(!restReply.isSuccess());
+ QVERIFY(restReply.hasError());
+ QCOMPARE(restReply.error(), QNetworkReply::ProtocolUnknownError);
+ QCOMPARE(restReply.networkReply()->isFinished(), true);
+ restReply.networkReply()->deleteLater();
}
m_actualReplies.clear();
m_expectedReplies.clear();
- managerFinishedSpy.clear();
// -- Test with data
- reply = manager.post(request, data);
- m_expectedReplies.append(reply);
- QObject::connect(reply, &QRestReply::finished, lambdaHandler);
-
// With lambda callback, without context object
m_expectedReplies.append(manager.post(request, data, nullptr, lambdaHandler));
m_expectedReplies.append(manager.post(request, data, nullptr,
- [this](QRestReply *reply){m_actualReplies.append(reply);}));
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
// With lambda callback and context object
m_expectedReplies.append(manager.post(request, data, this, lambdaHandler));
m_expectedReplies.append(manager.post(request, data, this,
- [this](QRestReply *reply){m_actualReplies.append(reply);}));
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
// With member callback and context object
m_expectedReplies.append(manager.post(request, data,
this, &tst_QRestAccessManager::memberHandler));
@@ -404,31 +375,27 @@ void tst_QRestAccessManager::callbacks()
// Let requests finish
QTRY_COMPARE(m_actualReplies.size(), m_expectedReplies.size());
- QTRY_COMPARE(managerFinishedSpy.size(), m_actualReplies.size());
for (auto reply: m_actualReplies) {
- QVERIFY(!reply->isSuccess());
- QVERIFY(reply->hasError());
- QCOMPARE(reply->error(), QNetworkReply::ProtocolUnknownError);
- QCOMPARE(reply->isFinished(), true);
+ QRestReply restReply(reply);
+ QVERIFY(!restReply.isSuccess());
+ QVERIFY(restReply.hasError());
+ QCOMPARE(restReply.error(), QNetworkReply::ProtocolUnknownError);
+ QCOMPARE(restReply.networkReply()->isFinished(), true);
reply->deleteLater();
}
m_actualReplies.clear();
m_expectedReplies.clear();
- managerFinishedSpy.clear();
// -- Test GET with data separately, as GET provides methods that are usable with and
- // without data, and fairly easy to get the qrestaccessmanager.h template SFINAE subtly wrong
- reply = manager.get(request, data);
- m_expectedReplies.append(reply);
- QObject::connect(reply, &QRestReply::finished, lambdaHandler);
+ // without data, and fairly easy to get the qrestaccessmanager.h template SFINAE subtly wrong.
// With lambda callback, without context object
m_expectedReplies.append(manager.get(request, data, nullptr, lambdaHandler));
m_expectedReplies.append(manager.get(request, data, nullptr,
- [this](QRestReply *reply){m_actualReplies.append(reply);}));
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
// With lambda callback and context object
m_expectedReplies.append(manager.get(request, data, this, lambdaHandler));
m_expectedReplies.append(manager.get(request, data, this,
- [this](QRestReply *reply){m_actualReplies.append(reply);}));
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
// With member callback and context object
m_expectedReplies.append(manager.get(request, data,
this, &tst_QRestAccessManager::memberHandler));
@@ -439,75 +406,30 @@ void tst_QRestAccessManager::callbacks()
// Let requests finish
QTRY_COMPARE(m_actualReplies.size(), m_expectedReplies.size());
- QTRY_COMPARE(managerFinishedSpy.size(), m_actualReplies.size());
for (auto reply: m_actualReplies) {
- QVERIFY(!reply->isSuccess());
- QVERIFY(reply->hasError());
- QCOMPARE(reply->error(), QNetworkReply::ProtocolUnknownError);
- QCOMPARE(reply->isFinished(), true);
- reply->deleteLater();
+ QRestReply restReply(reply);
+ QVERIFY(!restReply.isSuccess());
+ QVERIFY(restReply.hasError());
+ QCOMPARE(restReply.error(), QNetworkReply::ProtocolUnknownError);
+ QCOMPARE(restReply.networkReply()->isFinished(), true);
+ restReply.networkReply()->deleteLater();
}
m_actualReplies.clear();
m_expectedReplies.clear();
- managerFinishedSpy.clear();
-}
-
-class RestWorker : public QObject
-{
- Q_OBJECT
-public:
- explicit RestWorker(QObject *parent = nullptr) : QObject(parent)
- {
- m_manager = new QRestAccessManager(this);
- }
- QRestAccessManager *m_manager;
-
-public slots:
- void issueRestRequest()
- {
- QNetworkRequest request{u"i_dont_exist"_s};
- m_manager->get(request, this, [this](QRestReply *reply){
- emit result(reply->body());
- });
- }
-signals:
- void result(const QByteArray &data);
-};
-
-void tst_QRestAccessManager::threading()
-{
- // QRestAccessManager and QRestReply are only allowed to use in the thread they live in.
-
- // A "sanity test" for checking that there are no problems with running the QRestAM
- // in another thread.
- QThread restWorkThread;
- RestWorker restWorker;
- restWorker.moveToThread(&restWorkThread);
-
- QList<QByteArray> results;
- QObject::connect(&restWorker, &RestWorker::result, this, [&](const QByteArray &data){
- results.append(data);
- });
- restWorkThread.start();
-
- QMetaObject::invokeMethod(&restWorker, &RestWorker::issueRestRequest);
- QTRY_COMPARE(results.size(), 1);
- restWorkThread.quit();
- restWorkThread.wait();
}
void tst_QRestAccessManager::destruction()
{
- QRestAccessManager *manager = new QRestAccessManager;
- manager->setDeletesRepliesOnFinished(false); // Don't autodelete so we can compare results later
+ std::unique_ptr<QNetworkAccessManager> qnam = std::make_unique<QNetworkAccessManager>();
+ std::unique_ptr<QRestAccessManager> manager = std::make_unique<QRestAccessManager>(qnam.get());
QNetworkRequest request{u"i_dont_exist"_s}; // Will result in ProtocolUnknown error
m_expectedReplies.clear();
m_actualReplies.clear();
- auto handler = [this](QRestReply *reply) { m_actualReplies.append(reply); };
+ auto handler = [this](QRestReply &reply) { m_actualReplies.append(reply.networkReply()); };
// Delete reply immediately, make sure nothing bad happens and that there is no callback
- QRestReply *reply = manager->get(request, this, handler);
- delete reply;
+ QNetworkReply *networkReply = manager->get(request, this, handler);
+ delete networkReply;
QTest::qWait(20); // allow some time for the callback to arrive (it shouldn't)
QCOMPARE(m_actualReplies.size(), m_expectedReplies.size()); // Both should be 0
@@ -516,118 +438,39 @@ void tst_QRestAccessManager::destruction()
manager->post(request, "data"_ba, this, handler);
QTest::ignoreMessage(QtWarningMsg, "Access manager destroyed while 2 requests were still"
" in progress");
- delete manager;
+ manager.reset();
QTest::qWait(20);
QCOMPARE(m_actualReplies.size(), m_expectedReplies.size()); // Both should be 0
-}
-
-void tst_QRestAccessManager::authentication()
-{
- // Test the case where server responds with '401' (authentication required).
- // The QRestAM emits an authenticationRequired signal, which is used to the username/password.
- // The QRestAM/QNAM underneath then automatically resends the request.
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
- HttpTestServer server;
- QTRY_VERIFY(server.isListening());
- QNetworkRequest request(server.url());
- QRestReply *replyFromServer = nullptr;
-
- HttpData serverSideRequest;
- server.setHandler([&](HttpData request, HttpData &response, ResponseControl&) {
- if (!request.headers.contains(Header::Authorization)) {
- response.status = 401;
- response.headers.append(Header::WWWAuthenticate, "Basic realm=\"secret_place\""_ba);
- } else {
- response.status = 200;
- }
- serverSideRequest = request; // store for checking later the 'Authorization' header value
- });
- QObject::connect(&manager, &QRestAccessManager::authenticationRequired, this,
- [](QRestReply*, QAuthenticator *authenticator) {
- authenticator->setUser(u"a_user"_s);
- authenticator->setPassword(u"a_password"_s);
- });
-
- // Issue a GET request without any authorization data.
- int finishedCount = 0;
- manager.get(request, this, [&](QRestReply *reply) {
- finishedCount++;
- replyFromServer = reply;
- });
- QTRY_VERIFY(replyFromServer);
- // Server and QRestAM/QNAM exchange req/res twice, but finished() should be emitted just once
- QCOMPARE(finishedCount, 1);
- const auto resultHeaders = serverSideRequest.headers.values(Header::Authorization);
- QVERIFY(!resultHeaders.empty());
- QCOMPARE(resultHeaders.first(), "Basic YV91c2VyOmFfcGFzc3dvcmQ="_ba);
-}
-
-void tst_QRestAccessManager::userInfo()
-{
- // Tests setting of username and password into the request factory
- using ReplyPtr = std::unique_ptr<QRestReply, QScopedPointerDeleteLater>;
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
- HttpTestServer server;
- QTRY_VERIFY(server.isListening());
-
- QNetworkRequestFactory factory(server.url());
- factory.setUserName(u"a_user"_s);
- const auto password = u"a_password"_s;
- factory.setPassword(password);
-
- HttpData serverSideRequest;
- server.setHandler([&](HttpData request, HttpData& response, ResponseControl&) {
- if (!request.headers.contains(Header::Authorization)) {
- response.status = 401;
- response.headers.append(Header::WWWAuthenticate,"Basic realm=\"secret_place\""_ba);
- } else {
- response.status = 200;
- }
- serverSideRequest = request; // store for checking later the 'Authorization' header value
- });
-
- ReplyPtr reply(manager.get(factory.createRequest()));
- QTRY_VERIFY(reply.get()->isFinished());
- QVERIFY(reply.get()->isSuccess());
- QCOMPARE(reply.get()->httpStatus(), 200);
- const auto resultHeaders = serverSideRequest.headers.values(Header::Authorization);
- QVERIFY(!resultHeaders.empty());
- QCOMPARE(resultHeaders.first(), "Basic YV91c2VyOmFfcGFzc3dvcmQ="_ba);
-
- // Verify that debug output does not contain password
- QString debugOutput;
- QDebug debug(&debugOutput);
- debug << factory;
- QVERIFY(debugOutput.contains("password = (is set)"));
- QVERIFY(!debugOutput.contains(password));
+ // Destroy the underlying QNAM while requests in progress
+ manager = std::make_unique<QRestAccessManager>(qnam.get());
+ manager->get(request, this, handler);
+ manager->post(request, "data"_ba, this, handler);
+ qnam.reset();
+ QTest::qWait(20);
+ QCOMPARE(m_actualReplies.size(), m_expectedReplies.size()); // Both should be 0
}
#define VERIFY_HTTP_ERROR_STATUS(STATUS) \
+{ \
serverSideResponse.status = STATUS; \
- reply = manager.get(request); \
- QObject::connect(reply, &QRestReply::errorOccurred, this, \
- [&](){ errorSignalReceived = true; }); \
- QTRY_VERIFY(reply->isFinished()); \
- QVERIFY(!errorSignalReceived); \
- QVERIFY(!reply->hasError()); \
- QCOMPARE(reply->httpStatus(), serverSideResponse.status); \
- QCOMPARE(reply->error(), QNetworkReply::NetworkError::NoError); \
- QVERIFY(!reply->isSuccess()); \
- reply->deleteLater(); \
+ QRestReply restReply(manager.get(request)); \
+ QTRY_VERIFY(restReply.networkReply()->isFinished()); \
+ QVERIFY(!restReply.hasError()); \
+ QCOMPARE(restReply.httpStatus(), serverSideResponse.status); \
+ QCOMPARE(restReply.error(), QNetworkReply::NetworkError::NoError); \
+ QVERIFY(!restReply.isSuccess()); \
+ restReply.networkReply()->deleteLater(); \
+} \
void tst_QRestAccessManager::errors()
{
// Tests the distinction between HTTP and other (network/protocol) errors
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
HttpTestServer server;
QTRY_VERIFY(server.isListening());
QNetworkRequest request(server.url());
- QRestReply *reply = nullptr;
- bool errorSignalReceived = false;
HttpData serverSideResponse; // The response data the server responds with
server.setHandler([&](HttpData, HttpData &response, ResponseControl &) {
@@ -656,48 +499,45 @@ void tst_QRestAccessManager::errors()
VERIFY_HTTP_ERROR_STATUS(504) // QNetworkReply::UnknownServerError
VERIFY_HTTP_ERROR_STATUS(505) // QNetworkReply::UnknownServerError
- // Test that actual network/protocol errors come through
- reply = manager.get({}); // Empty url
- QObject::connect(reply, &QRestReply::errorOccurred, this, [&](){ errorSignalReceived = true; });
- QTRY_VERIFY(reply->isFinished());
- QTRY_VERIFY(errorSignalReceived);
- QVERIFY(reply->hasError());
- QVERIFY(!reply->isSuccess());
- QCOMPARE(reply->error(), QNetworkReply::ProtocolUnknownError);
- reply->deleteLater();
- errorSignalReceived = false;
-
- reply = manager.get(QNetworkRequest{{"http://non-existent.foo.bar.test"}});
- QObject::connect(reply, &QRestReply::errorOccurred, this, [&](){ errorSignalReceived = true; });
- QTRY_VERIFY(reply->isFinished());
- QTRY_VERIFY(errorSignalReceived);
- QVERIFY(reply->hasError());
- QVERIFY(!reply->isSuccess());
- QCOMPARE(reply->error(), QNetworkReply::HostNotFoundError);
- reply->deleteLater();
- errorSignalReceived = false;
-
- reply = manager.get(request);
- QObject::connect(reply, &QRestReply::errorOccurred, this, [&](){ errorSignalReceived = true; });
- reply->abort();
- QTRY_VERIFY(reply->isFinished());
- QTRY_VERIFY(errorSignalReceived);
- QVERIFY(reply->hasError());
- QVERIFY(!reply->isSuccess());
- QCOMPARE(reply->error(), QNetworkReply::OperationCanceledError);
- reply->deleteLater();
- errorSignalReceived = false;
+ {
+ // Test that actual network/protocol errors come through
+ QRestReply restReply(manager.get({})); // Empty url
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QVERIFY(restReply.hasError());
+ QVERIFY(!restReply.isSuccess());
+ QCOMPARE(restReply.error(), QNetworkReply::ProtocolUnknownError);
+ restReply.networkReply()->deleteLater();
+ }
+
+ {
+ QRestReply restReply(manager.get(QNetworkRequest{{"http://non-existent.foo.bar.test"}}));
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QVERIFY(restReply.hasError());
+ QVERIFY(!restReply.isSuccess());
+ QCOMPARE(restReply.error(), QNetworkReply::HostNotFoundError);
+ restReply.networkReply()->deleteLater();
+ }
+
+ {
+ QRestReply restReply(manager.get(request));
+ restReply.networkReply()->abort();
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QVERIFY(restReply.hasError());
+ QVERIFY(!restReply.isSuccess());
+ QCOMPARE(restReply.error(), QNetworkReply::OperationCanceledError);
+ restReply.networkReply()->deleteLater();
+ }
}
void tst_QRestAccessManager::body()
{
// Test using QRestReply::body() data accessor
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
HttpTestServer server;
QTRY_VERIFY(server.isListening());
QNetworkRequest request(server.url());
- QRestReply *replyFromServer = nullptr;
+ QNetworkReply *networkReply = nullptr;
HttpData serverSideRequest; // The request data the server received
HttpData serverSideResponse; // The response data the server responds with
@@ -706,46 +546,57 @@ void tst_QRestAccessManager::body()
response = serverSideResponse;
});
- serverSideResponse.status = 200;
- serverSideResponse.body = "some_data"_ba;
- manager.get(request, this, [&](QRestReply *reply) { replyFromServer = reply; });
- QTRY_VERIFY(replyFromServer);
- QCOMPARE(replyFromServer->body(), serverSideResponse.body);
- QCOMPARE(replyFromServer->httpStatus(), serverSideResponse.status);
- QVERIFY(!replyFromServer->hasError());
- QVERIFY(replyFromServer->isSuccess());
- replyFromServer->deleteLater();
- replyFromServer = nullptr;
-
- serverSideResponse.body = ""_ba; // Empty
- manager.get(request, this, [&](QRestReply *reply) { replyFromServer = reply; });
- QTRY_VERIFY(replyFromServer);
- QCOMPARE(replyFromServer->body(), serverSideResponse.body);
- replyFromServer->deleteLater();
- replyFromServer = nullptr;
-
- serverSideResponse.status = 500;
- serverSideResponse.body = "some_other_data"_ba;
- manager.get(request, this, [&](QRestReply *reply) { replyFromServer = reply; });
- QTRY_VERIFY(replyFromServer);
- QCOMPARE(replyFromServer->body(), serverSideResponse.body);
- QCOMPARE(replyFromServer->httpStatus(), serverSideResponse.status);
- QVERIFY(!replyFromServer->hasError());
- QVERIFY(!replyFromServer->isSuccess());
- replyFromServer->deleteLater();
- replyFromServer = nullptr;
+ {
+ serverSideResponse.status = 200;
+ serverSideResponse.body = "some_data"_ba;
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ QCOMPARE(restReply.body(), serverSideResponse.body);
+ QCOMPARE(restReply.httpStatus(), serverSideResponse.status);
+ QVERIFY(!restReply.hasError());
+ QVERIFY(restReply.isSuccess());
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
+
+ {
+ serverSideResponse.status = 200;
+ serverSideResponse.body = ""_ba; // Empty
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ QCOMPARE(restReply.body(), serverSideResponse.body);
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
+
+ {
+ serverSideResponse.status = 500;
+ serverSideResponse.body = "some_other_data"_ba;
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ QCOMPARE(restReply.body(), serverSideResponse.body);
+ QCOMPARE(restReply.httpStatus(), serverSideResponse.status);
+ QVERIFY(!restReply.hasError());
+ QVERIFY(!restReply.isSuccess());
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
}
void tst_QRestAccessManager::json()
{
// Test using QRestReply::json() and jsonArray() data accessors
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
HttpTestServer server;
QTRY_VERIFY(server.isListening());
QNetworkRequest request(server.url());
- QRestReply *replyFromServer = nullptr;
+ QNetworkReply *networkReply = nullptr;
QJsonDocument responseJsonDocument;
+ std::optional<QJsonDocument> json;
QJsonParseError parseError;
HttpData serverSideRequest; // The request data the server received
@@ -756,95 +607,98 @@ void tst_QRestAccessManager::json()
response = serverSideResponse;
});
- // Test receiving valid json object
- serverSideResponse.body = "{\"key1\":\"value1\",""\"key2\":\"value2\"}\n"_ba;
- replyFromServer = manager.get(request);
- // Read unfinished reply
- QVERIFY(!replyFromServer->isFinished());
- QTest::ignoreMessage(QtWarningMsg, "Attempt to read json() of an unfinished reply, ignoring.");
- parseError.error = QJsonParseError::ParseError::DocumentTooLarge; // Reset to impossible value
- QVERIFY(!replyFromServer->json(&parseError));
- QCOMPARE(parseError.error, QJsonParseError::ParseError::NoError);
- // Read finished reply
- QTRY_VERIFY(replyFromServer->isFinished());
- parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
- std::optional json = replyFromServer->json(&parseError);
- QVERIFY(json);
- QCOMPARE(parseError.error, QJsonParseError::ParseError::NoError);
- responseJsonDocument = *json;
- QVERIFY(responseJsonDocument.isObject());
- QCOMPARE(responseJsonDocument["key1"], "value1");
- QCOMPARE(responseJsonDocument["key2"], "value2");
- replyFromServer->deleteLater();
- replyFromServer = nullptr;
-
- // Test receiving an invalid json object
- serverSideResponse.body = "foobar"_ba;
- manager.get(request, this, [&](QRestReply *reply) { replyFromServer = reply; });
- QTRY_VERIFY(replyFromServer);
- parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
- QVERIFY(!replyFromServer->json(&parseError).has_value()); // std::nullopt returned
- QCOMPARE_NE(parseError.error, QJsonParseError::ParseError::NoError);
- QCOMPARE_NE(parseError.error, QJsonParseError::ParseError::DocumentTooLarge);
- QCOMPARE_GT(parseError.offset, 0);
- replyFromServer->deleteLater();
- replyFromServer = nullptr;
-
- // Test receiving valid json array
- serverSideResponse.body = "[\"foo\", \"bar\"]\n"_ba;
- manager.get(request, this, [&](QRestReply *reply) { replyFromServer = reply; });
- QTRY_VERIFY(replyFromServer);
- parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
- json = replyFromServer->json(&parseError);
- QCOMPARE(parseError.error, QJsonParseError::ParseError::NoError);
- QVERIFY(json);
- responseJsonDocument = *json;
- QVERIFY(responseJsonDocument.isArray());
- QCOMPARE(responseJsonDocument.array().size(), 2);
- QCOMPARE(responseJsonDocument[0].toString(), "foo"_L1);
- QCOMPARE(responseJsonDocument[1].toString(), "bar"_L1);
- replyFromServer->deleteLater();
- replyFromServer = nullptr;
-
- // Test receiving an invalid json array
- serverSideResponse.body = "foobar"_ba;
- manager.get(request, this, [&](QRestReply *reply) { replyFromServer = reply; });
- QTRY_VERIFY(replyFromServer);
- parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
- QVERIFY(!replyFromServer->json(&parseError).has_value()); // std::nullopt returned
- QCOMPARE_NE(parseError.error, QJsonParseError::ParseError::NoError);
- QCOMPARE_NE(parseError.error, QJsonParseError::ParseError::DocumentTooLarge);
- QCOMPARE_GT(parseError.offset, 0);
- replyFromServer->deleteLater();
- replyFromServer = nullptr;
+ {
+ // Test receiving valid json object
+ serverSideResponse.body = "{\"key1\":\"value1\",""\"key2\":\"value2\"}\n"_ba;
+ networkReply = manager.get(request);
+ // Read unfinished reply
+ QVERIFY(!networkReply->isFinished());
+ QTest::ignoreMessage(QtWarningMsg, "Attempt to read json() of an unfinished reply, ignoring.");
+ parseError.error = QJsonParseError::ParseError::DocumentTooLarge; // Reset to impossible value
+ QRestReply restReply(networkReply);
+ QVERIFY(!restReply.json(&parseError));
+ QCOMPARE(parseError.error, QJsonParseError::ParseError::NoError);
+ // Read finished reply
+ QTRY_VERIFY(networkReply->isFinished());
+ parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
+ json = restReply.json(&parseError);
+ QVERIFY(json);
+ QCOMPARE(parseError.error, QJsonParseError::ParseError::NoError);
+ responseJsonDocument = *json;
+ QVERIFY(responseJsonDocument.isObject());
+ QCOMPARE(responseJsonDocument["key1"], "value1");
+ QCOMPARE(responseJsonDocument["key2"], "value2");
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
+
+ {
+ // Test receiving an invalid json object
+ serverSideResponse.body = "foobar"_ba;
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
+ QVERIFY(!restReply.json(&parseError).has_value()); // std::nullopt returned
+ QCOMPARE_NE(parseError.error, QJsonParseError::ParseError::NoError);
+ QCOMPARE_NE(parseError.error, QJsonParseError::ParseError::DocumentTooLarge);
+ QCOMPARE_GT(parseError.offset, 0);
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
+
+ {
+ // Test receiving valid json array
+ serverSideResponse.body = "[\"foo\", \"bar\"]\n"_ba;
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
+ json = restReply.json(&parseError);
+ QCOMPARE(parseError.error, QJsonParseError::ParseError::NoError);
+ QVERIFY(json);
+ responseJsonDocument = *json;
+ QVERIFY(responseJsonDocument.isArray());
+ QCOMPARE(responseJsonDocument.array().size(), 2);
+ QCOMPARE(responseJsonDocument[0].toString(), "foo"_L1);
+ QCOMPARE(responseJsonDocument[1].toString(), "bar"_L1);
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
}
#define VERIFY_TEXT_REPLY_OK \
- manager.get(request, this, [&](QRestReply *reply) { replyFromServer = reply; }); \
- QTRY_VERIFY(replyFromServer); \
- responseString = replyFromServer->text(); \
+{ \
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); }); \
+ QTRY_VERIFY(networkReply); \
+ QRestReply restReply(networkReply); \
+ responseString = restReply.text(); \
QCOMPARE(responseString, sourceString); \
- replyFromServer->deleteLater(); \
- replyFromServer = nullptr; \
+ networkReply->deleteLater(); \
+ networkReply = nullptr; \
+}
#define VERIFY_TEXT_REPLY_ERROR(WARNING_MESSAGE) \
- manager.get(request, this, [&](QRestReply *reply) { replyFromServer = reply; }); \
- QTRY_VERIFY(replyFromServer); \
+{ \
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); }); \
+ QTRY_VERIFY(networkReply); \
QTest::ignoreMessage(QtWarningMsg, WARNING_MESSAGE); \
- responseString = replyFromServer->text(); \
+ QRestReply restReply(networkReply); \
+ responseString = restReply.text(); \
QVERIFY(responseString.isEmpty()); \
- replyFromServer->deleteLater(); \
- replyFromServer = nullptr; \
+ networkReply->deleteLater(); \
+ networkReply = nullptr; \
+}
void tst_QRestAccessManager::text()
{
// Test using QRestReply::text() data accessor with various text encodings
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
HttpTestServer server;
QTRY_VERIFY(server.isListening());
QNetworkRequest request(server.url());
- QRestReply *replyFromServer = nullptr;
+ QNetworkReply *networkReply = nullptr;
QJsonObject responseJsonObject;
QStringEncoder encUTF8("UTF-8");
@@ -899,16 +753,19 @@ void tst_QRestAccessManager::text()
serverSideResponse.body = encUTF32(sourceString);
VERIFY_TEXT_REPLY_OK;
- // Unsuccessful UTF-32, wrong encoding indicated (indicated charset UTF-32 but data is UTF-8)
- serverSideResponse.headers.removeAll(Header::ContentType);
- serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=UTF-32"_ba);
- serverSideResponse.body = encUTF8(sourceString);
- manager.get(request, this, [&](QRestReply *reply) { replyFromServer = reply; });
- QTRY_VERIFY(replyFromServer);
- responseString = replyFromServer->text();
- QCOMPARE_NE(responseString, sourceString);
- replyFromServer->deleteLater();
- replyFromServer = nullptr;
+ {
+ // Unsuccessful UTF-32, wrong encoding indicated (indicated UTF-32 but data is UTF-8)
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=UTF-32"_ba);
+ serverSideResponse.body = encUTF8(sourceString);
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ responseString = restReply.text();
+ QCOMPARE_NE(responseString, sourceString);
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
// Unsupported encoding
serverSideResponse.headers.removeAll(Header::ContentType);
@@ -926,10 +783,11 @@ void tst_QRestAccessManager::text()
void tst_QRestAccessManager::textStreaming()
{
// Tests textual data received in chunks
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
HttpTestServer server;
QTRY_VERIFY(server.isListening());
+ QNetworkRequest request(server.url());
// Create long text data
const QString expectedData = u"사랑abcd€fghiklmnΩpqrstuvwx愛사랑A사랑BCD€FGHIJKLMNΩPQRsTUVWXYZ愛"_s;
@@ -949,143 +807,37 @@ void tst_QRestAccessManager::textStreaming()
control.responseChunkSize = 5; // tell testserver to send data in chunks of this size
});
- QNetworkRequest request(server.url());
- QRestReply *reply = manager.get(request);
- QObject::connect(reply, &QRestReply::readyRead, this, [&](QRestReply *reply) {
- cumulativeReceivedText += reply->text();
- // Tell testserver that test is ready for next chunk
- responseControl->readyForNextChunk = true;
- });
- QTRY_VERIFY(reply->isFinished());
- QCOMPARE(cumulativeReceivedText, expectedData);
-
- cumulativeReceivedText.clear();
- // Broken UTF-8 characters after first five ok characters
- serverSideResponse.body =
- "12345"_ba + "\xF0\x28\x8C\x28\xA0\xB0\xC0\xD0" + "abcde"_ba;
- reply = manager.get(request);
- QObject::connect(reply, &QRestReply::readyRead, this, [&](QRestReply *reply) {
- static bool firstTime = true;
- if (!firstTime) // First text part is without warnings
- QTest::ignoreMessage(QtWarningMsg, "text() Decoding error occurred");
- firstTime = false;
- cumulativeReceivedText += reply->text();
- // Tell testserver that test is ready for next chunk
- responseControl->readyForNextChunk = true;
- });
- QTRY_VERIFY(reply->isFinished());
- QCOMPARE(cumulativeReceivedText, "12345"_ba);
-}
-
-void tst_QRestAccessManager::download()
-{
- // Test case where data is received in chunks.
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
- HttpTestServer server;
- QTRY_VERIFY(server.isListening());
- QNetworkRequest request(server.url());
- HttpData serverSideResponse; // The response data the server responds with
- constexpr qsizetype dataSize = 1 * 1024 * 1024; // 1 MB
- QByteArray expectedData{dataSize, 0};
- for (qsizetype i = 0; i < dataSize; ++i) // initialize the data we download
- expectedData[i] = i % 100;
- QByteArray cumulativeReceivedData;
- qsizetype cumulativeReceivedBytesAvailable = 0;
-
- serverSideResponse.body = expectedData;
- ResponseControl *responseControl = nullptr;
- serverSideResponse.status = 200;
- // Set content-length header so that underlying QNAM is able to report bytesTotal correctly
- serverSideResponse.headers.append(Header::ContentType,
- QString::number(expectedData.size()).toLatin1());
- server.setHandler([&](HttpData, HttpData &response, ResponseControl &control) {
- response = serverSideResponse;
- responseControl = &control; // store for later
- control.responseChunkSize = 1024; // tell testserver to send data in chunks of this size
- });
-
- QRestReply* reply = manager.get(request, this, [&responseControl](QRestReply */*reply*/){
- responseControl = nullptr; // all finished, no more need for controlling the response
- });
-
- QObject::connect(reply, &QRestReply::readyRead, this, [&](QRestReply *reply) {
- static bool testOnce = true;
- if (!reply->isFinished() && testOnce) {
- // Test once that reading json of an unfinished reply will not work
- testOnce = false;
- QTest::ignoreMessage(QtWarningMsg, "Attempt to read json() of an unfinished"
- " reply, ignoring.");
- reply->json();
- }
-
- cumulativeReceivedBytesAvailable += reply->bytesAvailable();
- cumulativeReceivedData += reply->body();
- // Tell testserver that test is ready for next chunk
- responseControl->readyForNextChunk = true;
- });
-
- qint64 totalBytes = 0;
- qint64 receivedBytes = 0;
- QObject::connect(reply, &QRestReply::downloadProgress, this,
- [&](qint64 bytesReceived, qint64 bytesTotal) {
- if (totalBytes == 0 && bytesTotal > 0)
- totalBytes = bytesTotal;
- receivedBytes = bytesReceived;
- });
- QTRY_VERIFY(reply->isFinished());
- reply->deleteLater();
- reply = nullptr;
- // Checks specific for readyRead() and bytesAvailable()
- QCOMPARE(cumulativeReceivedData, expectedData);
- QCOMPARE(cumulativeReceivedBytesAvailable, expectedData.size());
- // Checks specific for downloadProgress()
- QCOMPARE(totalBytes, expectedData.size());
- QCOMPARE(receivedBytes, expectedData.size());
-}
-
-void tst_QRestAccessManager::upload()
-{
- // This test tests uploadProgress signal
- QRestAccessManager manager;
- manager.setDeletesRepliesOnFinished(false);
- HttpTestServer server;
- QTRY_VERIFY(server.isListening());
- QNetworkRequest request(server.url());
- request.setRawHeader("Content-Type"_ba, "text/plain"); // To silence missing content-type warn
- QByteArray expectedData{1 * 1024 * 1024, 0}; // 1 MB
- server.setHandler([&](HttpData, HttpData &, ResponseControl &) {});
-
- QRestReply* reply = manager.post(request, expectedData);
- QSignalSpy uploadProgressSpy(reply, &QRestReply::uploadProgress);
- QTRY_VERIFY(reply->isFinished());
- QVERIFY(!uploadProgressSpy.isEmpty());
- reply->deleteLater();
-
- // Check that bytesTotal is correct already in the first signal
- const QList<QVariant> first = uploadProgressSpy.first();
- QCOMPARE(first.size(), 3);
- QCOMPARE(first.at(1).toLongLong(), expectedData.size());
-
- // Check that we sent all bytes
- const QList<QVariant> last = uploadProgressSpy.last();
- QCOMPARE(last.size(), 3);
- QEXPECT_FAIL("", "Fails due to QTBUG-44782", Continue);
- QCOMPARE(last.at(0).toLongLong(), expectedData.size());
-}
-
-void tst_QRestAccessManager::timeout()
-{
- constexpr auto defaultTimeout = 0ms;
- constexpr auto timeout = 150ms;
-
- QRestAccessManager manager;
- QCOMPARE(manager.transferTimeout(), defaultTimeout);
- QCOMPARE(manager.networkAccessManager()->transferTimeoutAsDuration(), defaultTimeout);
+ {
+ QRestReply restReply(manager.get(request));
+ QObject::connect(restReply.networkReply(), &QNetworkReply::readyRead, this, [&]() {
+ cumulativeReceivedText += restReply.text();
+ // Tell testserver that test is ready for next chunk
+ responseControl->readyForNextChunk = true;
+ });
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QCOMPARE(cumulativeReceivedText, expectedData);
+ restReply.networkReply()->deleteLater();
+ }
- manager.setTransferTimeout(timeout);
- QCOMPARE(manager.transferTimeout(), timeout);
- QCOMPARE(manager.networkAccessManager()->transferTimeoutAsDuration(), timeout);
+ {
+ cumulativeReceivedText.clear();
+ // Broken UTF-8 characters after first five ok characters
+ serverSideResponse.body =
+ "12345"_ba + "\xF0\x28\x8C\x28\xA0\xB0\xC0\xD0" + "abcde"_ba;
+ QRestReply restReply(manager.get(request));
+ QObject::connect(restReply.networkReply(), &QNetworkReply::readyRead, this, [&]() {
+ static bool firstTime = true;
+ if (!firstTime) // First text part is without warnings
+ QTest::ignoreMessage(QtWarningMsg, "text() Decoding error occurred");
+ firstTime = false;
+ cumulativeReceivedText += restReply.text();
+ // Tell testserver that test is ready for next chunk
+ responseControl->readyForNextChunk = true;
+ });
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QCOMPARE(cumulativeReceivedText, "12345"_ba);
+ restReply.networkReply()->deleteLater();
+ }
}
QTEST_MAIN(tst_QRestAccessManager)