Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F308055
D210.1745364398.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
D210.1745364398.diff
View Options
diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,7 +21,7 @@
endif()
set(QT_MAJOR_VERSION ${kazv_KF_QT_MAJOR_VERSION})
set(KF_MAJOR_VERSION ${kazv_KF_QT_MAJOR_VERSION})
-set(QT_MIN_VERSION 6.5.0)
+set(QT_MIN_VERSION 6.8.0)
set(KF_MIN_VERSION 6.0.0)
option(kazv_LINK_BREEZE_ICONS "Link to Breeze icons library" OFF)
@@ -52,7 +52,7 @@
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} REQUIRED COMPONENTS
Core Gui Qml QuickControls2 Svg Concurrent Widgets
- Multimedia Test Network QuickTest
+ Multimedia Test Network QuickTest HttpServer
)
qt6_policy(SET QTP0001 NEW)
set(kazv_KF_EXTRA_MODULES)
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -35,6 +35,11 @@
LINK_LIBRARIES Qt${QT_MAJOR_VERSION}::Test kazvtestlib
)
+ecm_add_test(
+ kazv-io-job-test.cpp
+ LINK_LIBRARIES Qt${QT_MAJOR_VERSION}::Test Qt${QT_MAJOR_VERSION}::HttpServer kazvtestlib
+)
+
ecm_add_test(
quick-test.cpp
TEST_NAME quicktest
diff --git a/src/tests/kazv-io-job-test.cpp b/src/tests/kazv-io-job-test.cpp
new file mode 100644
--- /dev/null
+++ b/src/tests/kazv-io-job-test.cpp
@@ -0,0 +1,214 @@
+/*
+ * This file is part of kazv.
+ * SPDX-FileCopyrightText: 2025 nannanko <nannanko@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <kazv-defs.hpp>
+#include <kazv-io-job.hpp>
+
+#include <QObject>
+#include <QtTest>
+#include <QHttpServer>
+#include <QTcpServer>
+#include <QThread>
+#include <QTemporaryFile>
+#include <QCryptographicHash>
+#include <QString>
+#include <QHttpServerResponse>
+#include <QHttpServerRequest>
+#include <QSignalSpy>
+#include <QJsonObject>
+
+using namespace Qt::Literals::StringLiterals;
+
+class KazvIOJobTest : public QObject
+{
+ Q_OBJECT
+
+private:
+ QHttpServer httpServer;
+ QTcpServer tcpServer;
+ QThread serverThread;
+ quint16 port;
+
+ QTemporaryFile downloadFile;
+ QTemporaryFile uploadFile;
+ QCryptographicHash downloadFileHash{QCryptographicHash::Sha256};
+ QString hashStr;
+
+ const QString downloadEndpoint = u"/download"_s;
+ const QString downloadPauseEndpoint = u"/download/pause"_s;
+ const QString downloadCancelEndpoint = u"/download/cancel"_s;
+ const QString uploadEndpoint = u"/_matrix/media/v3/upload"_s;
+ const char *fileContent = "some content";
+ QString serverUrl;
+
+private Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+ void testDownload();
+ void testDownloadPause();
+ void testDownloadCancel();
+ void testUpload();
+
+Q_SIGNALS:
+ void readyPause();
+ void readyResume();
+ void readyCancel();
+ void canceled();
+};
+
+void KazvIOJobTest::initTestCase()
+{
+ downloadFile.open();
+ downloadFile.write(fileContent);
+ downloadFile.close();
+ downloadFileHash.addData(&downloadFile);
+ hashStr = QString::fromUtf8(downloadFileHash.result().toBase64(
+ QByteArray::Base64Encoding | QByteArray::OmitTrailingEquals));
+
+ httpServer.route(downloadEndpoint, [this](QHttpServerResponder &res) {
+ downloadFile.open();
+ res.writeBeginChunked("application/octet-stream");
+ res.writeEndChunked(downloadFile.readAll());
+ downloadFile.close();
+ });
+ httpServer.route(downloadPauseEndpoint, [this](QHttpServerResponder &res) {
+ downloadFile.open();
+ res.writeBeginChunked("application/octet-stream");
+ QSignalSpy qs{this, &KazvIOJobTest::readyResume};
+ Q_EMIT readyPause();
+ QVERIFY(qs.wait());
+ res.writeEndChunked(downloadFile.readAll());
+ downloadFile.close();
+ });
+ httpServer.route(downloadCancelEndpoint, [this](QHttpServerResponder &res) {
+ downloadFile.open();
+ res.writeBeginChunked("application/octet-stream");
+ QSignalSpy qs{this, &KazvIOJobTest::canceled};
+ Q_EMIT readyCancel();
+ QVERIFY(qs.wait());
+ return;
+ });
+ httpServer.route(uploadEndpoint, [this](const QHttpServerRequest &req) {
+ uploadFile.open();
+ uploadFile.write(req.body());
+ uploadFile.close();
+ auto resJson = QJsonObject{
+ {u"content_uri"_s, u"mxc://uri"_s}};
+ return QHttpServerResponse{
+ resJson, QHttpServerResponse::StatusCode::Ok};
+ });
+ if (!tcpServer.listen() || !httpServer.bind(&tcpServer)) {
+ QFAIL("Cannot start the Http server!");
+ }
+ port = tcpServer.serverPort();
+ serverUrl = u"http://localhost:"_s + QString::number(port);
+ httpServer.moveToThread(&serverThread);
+ serverThread.start();
+}
+
+void KazvIOJobTest::cleanupTestCase()
+{
+ serverThread.quit();
+ serverThread.wait();
+}
+
+void KazvIOJobTest::testDownload()
+{
+ QTemporaryFile saveFile{};
+ saveFile.open();
+ auto url = QUrl{serverUrl + downloadEndpoint};
+ KazvIODownloadJob job{saveFile.fileName(), url, false, hashStr};
+ QCOMPARE(job.fileName(), saveFile.fileName());
+ QSignalSpy qs{&job, &KazvIOBaseJob::result};
+ QVERIFY(qs.wait());
+ QVERIFY(job.isResulted());
+
+ auto args = qs.takeFirst();
+ QCOMPARE(qvariant_cast<KazvIOBaseJob::ErrorCode>(args.at(0)),
+ KazvIOBaseJob::NoError);
+
+ downloadFile.open();
+ QTRY_COMPARE(downloadFile.readAll(), saveFile.readAll());
+ downloadFile.close();
+ saveFile.close();
+}
+
+void KazvIOJobTest::testDownloadPause()
+{
+ QTemporaryFile saveFile{};
+ saveFile.open();
+ auto url = QUrl{serverUrl + downloadPauseEndpoint};
+ KazvIODownloadJob job{saveFile.fileName(), url, false, hashStr};
+ QSignalSpy qsResult{&job, &KazvIOBaseJob::result};
+ QSignalSpy qsPause{this, &KazvIOJobTest::readyPause};
+ QVERIFY(qsPause.wait());
+ job.suspend();
+ QVERIFY(job.isSuspended());
+ job.resume();
+ Q_EMIT readyResume();
+ QVERIFY(qsResult.wait());
+ QVERIFY(job.isResulted());
+
+ auto args = qsResult.takeFirst();
+ QCOMPARE(qvariant_cast<KazvIOBaseJob::ErrorCode>(args.at(0)),
+ KazvIOBaseJob::NoError);
+
+ downloadFile.open();
+ QTRY_COMPARE(downloadFile.readAll(), saveFile.readAll());
+ downloadFile.close();
+ saveFile.close();
+}
+
+void KazvIOJobTest::testDownloadCancel()
+{
+ QTemporaryFile saveFile{};
+ saveFile.open();
+ auto url = QUrl{serverUrl + downloadCancelEndpoint};
+ KazvIODownloadJob job{saveFile.fileName(), url, false, hashStr};
+ QSignalSpy qsCancel{this, &KazvIOJobTest::readyCancel};
+ QSignalSpy qsResult{&job, &KazvIOBaseJob::result};
+ QVERIFY(qsCancel.wait());
+ job.cancel();
+ Q_EMIT canceled();
+ QTRY_COMPARE(qsResult.count(), 1);
+ QVERIFY(job.isResulted());
+
+ auto args = qsResult.takeFirst();
+ QCOMPARE(qvariant_cast<KazvIOBaseJob::ErrorCode>(args.at(0)),
+ KazvIOBaseJob::UserCancel);
+
+ downloadFile.open();
+ QTRY_COMPARE(""_ba, saveFile.readAll());
+ downloadFile.close();
+ saveFile.close();
+}
+
+void KazvIOJobTest::testUpload()
+{
+ QTemporaryFile file;
+ file.open();
+ file.write(fileContent);
+ auto url = QUrl{serverUrl};
+ KazvIOUploadJob job{
+ file.fileName(), url, false, nullptr, u""_s, u"token"_s};
+ QCOMPARE(job.fileName(), file.fileName());
+ QSignalSpy qs{&job, &KazvIOBaseJob::result};
+ QVERIFY(qs.wait());
+ QVERIFY(job.isResulted());
+
+ auto args = qs.takeFirst();
+ QCOMPARE(qvariant_cast<KazvIOBaseJob::ErrorCode>(args.at(0)),
+ KazvIOBaseJob::NoError);
+
+ uploadFile.open();
+ QTRY_COMPARE(uploadFile.readAll(), file.readAll());
+ uploadFile.close();
+ file.close();
+}
+
+QTEST_MAIN(KazvIOJobTest)
+
+#include "kazv-io-job-test.moc"
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 22, 4:26 PM (54 m, 4 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
100190
Default Alt Text
D210.1745364398.diff (7 KB)
Attached To
Mode
D210: Add kazv-io-job-test
Attached
Detach File
Event Timeline
Log In to Comment