File indexing completed on 2025-01-19 12:48:40
0001 /* 0002 SPDX-FileCopyrightText: 2019 Ben Gruber <bengruber250@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 // This test suite is based on those in ftptest.cpp and uses the same test files. 0008 0009 #include <kio/copyjob.h> 0010 #include <kio/storedtransferjob.h> 0011 0012 #include <QBuffer> 0013 #include <QProcess> 0014 #include <QStandardPaths> 0015 #include <QTest> 0016 0017 class WebDAVTest : public QObject 0018 { 0019 Q_OBJECT 0020 public: 0021 QUrl url(const QString &path) const 0022 { 0023 Q_ASSERT(path.startsWith(QChar('/'))); 0024 QUrl newUrl = m_url; 0025 newUrl.setPath(path); 0026 newUrl.setPort(port); 0027 return newUrl; 0028 } 0029 0030 QTemporaryDir m_remoteDir; 0031 QProcess m_daemonProc; 0032 QUrl m_url = QUrl("webdav://localhost"); 0033 static const int port = 30000; 0034 0035 private: 0036 static void runDaemon(QProcess &proc, const QTemporaryDir &remoteDir) 0037 { 0038 QVERIFY(remoteDir.isValid()); 0039 const QString exec = QStandardPaths::findExecutable("wsgidav"); 0040 if (exec.isEmpty()) { 0041 QFAIL("Could not find 'wsgidav' executable in PATH"); 0042 } 0043 proc.setProgram(exec); 0044 proc.setArguments( 0045 {QStringLiteral("--host=0.0.0.0"), QString("--port=%1").arg(port), QString("--root=%1").arg(remoteDir.path()), QStringLiteral("--auth=anonymous")}); 0046 proc.setProcessChannelMode(QProcess::ForwardedErrorChannel); 0047 proc.start(); 0048 QVERIFY(proc.waitForStarted()); 0049 QCOMPARE(proc.state(), QProcess::Running); 0050 // Wait for the daemon to print its port. That tells us both where it's listening 0051 // and also that it is ready to move ahead with testing. 0052 QVERIFY(QTest::qWaitFor( 0053 [&]() -> bool { 0054 const QString out = proc.readAllStandardOutput(); 0055 if (!out.isEmpty()) { 0056 qDebug() << "STDERR:" << out; 0057 } 0058 if (!out.endsWith("Serving on http://0.0.0.0:30000 ...\n")) { 0059 return false; 0060 } 0061 return true; 0062 }, 0063 5000)); 0064 } 0065 0066 private Q_SLOTS: 0067 void initTestCase() 0068 { 0069 // Force the http/webdav worker from our bindir as first choice. This specifically 0070 // works around the fact that the kioslave executable would load the worker from the system 0071 // as first choice instead of the one from the build dir. 0072 qputenv("QT_PLUGIN_PATH", QCoreApplication::applicationDirPath().toUtf8()); 0073 0074 // Start the webdav server. 0075 runDaemon(m_daemonProc, m_remoteDir); 0076 // Put a prefix on the stderr and stdout from the server. 0077 connect(&m_daemonProc, &QProcess::readyReadStandardError, this, [this] { 0078 qDebug() << "wsgidav STDERR:" << m_daemonProc.readAllStandardError(); 0079 }); 0080 connect(&m_daemonProc, &QProcess::readyReadStandardOutput, this, [this] { 0081 qDebug() << "wsgidav STDOUT:" << m_daemonProc.readAllStandardOutput(); 0082 }); 0083 0084 QStandardPaths::setTestModeEnabled(true); 0085 } 0086 0087 void cleanupTestCase() 0088 { 0089 m_daemonProc.terminate(); 0090 m_daemonProc.kill(); 0091 m_daemonProc.waitForFinished(); 0092 } 0093 0094 void init() 0095 { 0096 QCOMPARE(m_daemonProc.state(), QProcess::Running); 0097 } 0098 0099 void testGet() 0100 { 0101 const QString path("/testGet"); 0102 const auto url = this->url(path); 0103 const QString remotePath = m_remoteDir.path() + path; 0104 0105 QByteArray data("testBasicGet"); 0106 QFile file(remotePath); 0107 QVERIFY(file.open(QFile::WriteOnly)); 0108 file.write(data); 0109 file.close(); 0110 0111 auto job = KIO::storedGet(url); 0112 job->setUiDelegate(nullptr); 0113 QVERIFY2(job->exec(), qUtf8Printable(job->errorString())); 0114 QCOMPARE(job->data(), data); 0115 } 0116 0117 void testCopy() 0118 { 0119 const QString path("/testCopy"); 0120 const auto url = this->url(path); 0121 const QString remotePath = m_remoteDir.path() + path; 0122 const QString partPath = remotePath + ".part"; 0123 0124 QFile::remove(remotePath); 0125 QFile::remove(partPath); 0126 0127 const QString testCopy1 = QFINDTESTDATA("ftp/testCopy1"); 0128 QVERIFY(!testCopy1.isEmpty()); 0129 auto job = KIO::copy({QUrl::fromLocalFile(testCopy1)}, url, KIO::DefaultFlags); 0130 job->setUiDelegate(nullptr); 0131 QVERIFY2(job->exec(), qUtf8Printable(job->errorString())); 0132 QFile file(remotePath); 0133 QVERIFY(file.open(QFile::ReadOnly)); 0134 QCOMPARE(file.readAll(), QByteArray("part1\n")); 0135 } 0136 0137 void testCopyResume() 0138 { 0139 const QString path("/testCopy"); 0140 const auto url = this->url(path); 0141 const QString remotePath = m_remoteDir.path() + path; 0142 const QString partPath = remotePath + ".part"; 0143 0144 QFile::remove(remotePath); 0145 QFile::remove(partPath); 0146 const QString testCopy1 = QFINDTESTDATA("ftp/testCopy1"); 0147 QVERIFY(!testCopy1.isEmpty()); 0148 QVERIFY(QFile::copy(testCopy1, partPath)); 0149 0150 const QString testCopy2 = QFINDTESTDATA("ftp/testCopy2"); 0151 QVERIFY(!testCopy2.isEmpty()); 0152 auto job = KIO::copy({QUrl::fromLocalFile(testCopy2)}, url, KIO::Resume); 0153 job->setUiDelegate(nullptr); 0154 QVERIFY2(job->exec(), qUtf8Printable(job->errorString())); 0155 QFile file(remotePath); 0156 QVERIFY(file.open(QFile::ReadOnly)); 0157 QCOMPARE(file.readAll(), QByteArray("part1\npart2\n")); 0158 } 0159 0160 void testOverwriteCopy() 0161 { 0162 const QString path("/testOverwriteCopy"); 0163 const auto url = this->url(path); 0164 const QString remotePath = m_remoteDir.path() + path; 0165 0166 qDebug() << (m_remoteDir.path() + path); 0167 0168 // Create file 0169 const QString testCopy1 = QFINDTESTDATA("ftp/testCopy1"); 0170 QVERIFY(!testCopy1.isEmpty()); 0171 auto job1 = KIO::copy({QUrl::fromLocalFile(testCopy1)}, url, KIO::DefaultFlags); 0172 job1->setUiDelegate(nullptr); 0173 QVERIFY2(job1->exec(), qUtf8Printable(job1->errorString())); 0174 QFile file(remotePath); 0175 QVERIFY(file.open(QFile::ReadOnly)); 0176 QCOMPARE(file.readAll(), QByteArray("part1\n")); 0177 file.close(); 0178 0179 // File already exists, we expect it to be overwritten. 0180 const QString testOverwriteCopy2 = QFINDTESTDATA("ftp/testOverwriteCopy2"); 0181 QVERIFY(!testOverwriteCopy2.isEmpty()); 0182 auto job2 = KIO::copy({QUrl::fromLocalFile(testOverwriteCopy2)}, url, KIO::Overwrite); 0183 job2->setUiDelegate(nullptr); 0184 QVERIFY2(job2->exec(), qUtf8Printable(job2->errorString())); 0185 QVERIFY(file.open(QFile::ReadOnly)); 0186 QCOMPARE(file.readAll(), QByteArray("testOverwriteCopy2\n")); 0187 } 0188 0189 void testOverwriteCopyWithoutFlagFromLocal() 0190 { 0191 const QString path("/testOverwriteCopyWithoutFlag"); 0192 const auto url = this->url(path); 0193 0194 qDebug() << (m_remoteDir.path() + path); 0195 const QString testOverwriteCopy1 = QFINDTESTDATA("ftp/testOverwriteCopy1"); 0196 QVERIFY(!testOverwriteCopy1.isEmpty()); 0197 QVERIFY(QFile::copy(testOverwriteCopy1, m_remoteDir.path() + path)); 0198 0199 // Without overwrite flag. 0200 const QString testOverwriteCopy2 = QFINDTESTDATA("ftp/testOverwriteCopy2"); 0201 QVERIFY(!testOverwriteCopy2.isEmpty()); 0202 auto job = KIO::copy({QUrl::fromLocalFile(testOverwriteCopy2)}, url, KIO::DefaultFlags); 0203 job->setUiDelegate(nullptr); 0204 QVERIFY2(!job->exec(), qUtf8Printable(job->errorString())); 0205 QCOMPARE(job->error(), KIO::ERR_FILE_ALREADY_EXIST); 0206 QFile file(m_remoteDir.path() + path); 0207 QVERIFY(file.open(QFile::ReadOnly)); 0208 QCOMPARE(file.readAll(), QByteArray("testOverwriteCopy1\n")); // not 2! 0209 } 0210 0211 void testOverwriteCopyWithoutFlagFromRemote() 0212 { 0213 // This exercises a different code path than testOverwriteCopyWithoutFlagFromLocal 0214 const QString path("/testOverwriteCopyWithoutFlagRemote"); 0215 const QString dir_path("/dir"); 0216 const auto url = this->url(path); 0217 const auto dir_url = this->url(dir_path); 0218 0219 qDebug() << (m_remoteDir.path() + path); 0220 const auto testOverwriteCopy1 = QFINDTESTDATA("ftp/testOverwriteCopy1"); 0221 QVERIFY(!testOverwriteCopy1.isEmpty()); 0222 QVERIFY(QFile::copy(testOverwriteCopy1, m_remoteDir.path() + path)); 0223 QVERIFY(QDir(m_remoteDir.path()).mkdir("dir")); 0224 0225 // First copy should work. 0226 auto job = KIO::copy(url, dir_url, KIO::DefaultFlags); 0227 job->setUiDelegate(nullptr); 0228 QVERIFY2(job->exec(), qUtf8Printable(job->errorString())); 0229 0230 // Without overwrite flag. 0231 auto job2 = KIO::copy(url, dir_url, KIO::DefaultFlags); 0232 job2->setUiDelegate(nullptr); 0233 QVERIFY2(!job2->exec(), qUtf8Printable(job2->errorString())); 0234 QCOMPARE(job2->error(), KIO::ERR_FILE_ALREADY_EXIST); 0235 QFile file(m_remoteDir.path() + path); 0236 QVERIFY(file.open(QFile::ReadOnly)); 0237 QCOMPARE(file.readAll(), QByteArray("testOverwriteCopy1\n")); // not 2! 0238 } 0239 }; 0240 0241 QTEST_MAIN(WebDAVTest) 0242 #include "webdavtest.moc"