cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
483 lines
14 KiB
C++
483 lines
14 KiB
C++
/*
|
|
This file is part of the KDE project
|
|
SPDX-FileCopyrightText: 2004-2006 David Faure <faure@kde.org>
|
|
SPDX-FileCopyrightText: 2008 Norbert Frese <nf2@scheinwelt.at>
|
|
|
|
SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
|
|
#include "jobremotetest.h"
|
|
|
|
#include <QDebug>
|
|
#include <QDir>
|
|
#include <QEventLoop>
|
|
#include <QStandardPaths>
|
|
#include <QTest>
|
|
#include <QUrl>
|
|
|
|
#include <KLocalizedString>
|
|
|
|
#include <kio/copyjob.h>
|
|
#include <kio/deletejob.h>
|
|
#include <kio/directorysizejob.h>
|
|
#include <kio/filejob.h>
|
|
#include <kio/mkdirjob.h>
|
|
#include <kio/statjob.h>
|
|
#include <kio/storedtransferjob.h>
|
|
#include <kprotocolinfo.h>
|
|
// #include "kiotesthelper.h" // createTestFile etc.
|
|
|
|
QTEST_MAIN(JobRemoteTest)
|
|
|
|
QDateTime s_referenceTimeStamp;
|
|
|
|
// The code comes partly from jobtest.cpp
|
|
|
|
static QUrl remoteTmpUrl()
|
|
{
|
|
QString customDir(qgetenv("KIO_JOBREMOTETEST_REMOTETMP"));
|
|
if (customDir.isEmpty()) {
|
|
return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + '/');
|
|
} else {
|
|
// Could be a path or a URL
|
|
return QUrl::fromUserInput(customDir + '/');
|
|
}
|
|
}
|
|
|
|
static QString localTmpDir()
|
|
{
|
|
#ifdef Q_OS_WIN
|
|
return QDir::tempPath() + "/jobremotetest/";
|
|
#else
|
|
// This one needs to be on another partition
|
|
return QStringLiteral("/tmp/jobremotetest/");
|
|
#endif
|
|
}
|
|
|
|
static bool myExists(const QUrl &url)
|
|
{
|
|
KIO::Job *job = KIO::stat(url, KIO::StatJob::DestinationSide, KIO::StatBasic, KIO::HideProgressInfo);
|
|
job->setUiDelegate(nullptr);
|
|
return job->exec();
|
|
}
|
|
|
|
static bool myMkdir(const QUrl &url)
|
|
{
|
|
KIO::Job *job = KIO::mkdir(url, -1);
|
|
job->setUiDelegate(nullptr);
|
|
return job->exec();
|
|
}
|
|
|
|
void JobRemoteTest::initTestCase()
|
|
{
|
|
QStandardPaths::setTestModeEnabled(true);
|
|
|
|
s_referenceTimeStamp = QDateTime::currentDateTime().addSecs(-30); // 30 seconds ago
|
|
|
|
// Start with a clean base dir
|
|
cleanupTestCase();
|
|
QUrl url = remoteTmpUrl();
|
|
if (!myExists(url)) {
|
|
const bool ok = url.isLocalFile() ? QDir().mkpath(url.toLocalFile()) : myMkdir(url);
|
|
if (!ok) {
|
|
qFatal("couldn't create %s", qPrintable(url.toString()));
|
|
}
|
|
}
|
|
const bool ok = QDir().mkpath(localTmpDir());
|
|
if (!ok) {
|
|
qFatal("couldn't create %s", qPrintable(localTmpDir()));
|
|
}
|
|
}
|
|
|
|
static void delDir(const QUrl &pathOrUrl)
|
|
{
|
|
KIO::Job *job = KIO::del(pathOrUrl, KIO::HideProgressInfo);
|
|
job->setUiDelegate(nullptr);
|
|
job->exec();
|
|
}
|
|
|
|
void JobRemoteTest::cleanupTestCase()
|
|
{
|
|
delDir(remoteTmpUrl());
|
|
delDir(QUrl::fromLocalFile(localTmpDir()));
|
|
}
|
|
|
|
void JobRemoteTest::enterLoop()
|
|
{
|
|
QEventLoop eventLoop;
|
|
connect(this, &JobRemoteTest::exitLoop, &eventLoop, &QEventLoop::quit);
|
|
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
|
|
}
|
|
|
|
/////
|
|
|
|
void JobRemoteTest::putAndGet()
|
|
{
|
|
QUrl u(remoteTmpUrl());
|
|
u.setPath(u.path() + "putAndGetFile");
|
|
KIO::TransferJob *job = KIO::put(u, 0600, KIO::Overwrite | KIO::HideProgressInfo);
|
|
quint64 secsSinceEpoch = QDateTime::currentSecsSinceEpoch(); // Use second granularity, supported on all filesystems
|
|
QDateTime mtime = QDateTime::fromSecsSinceEpoch(secsSinceEpoch - 30); // 30 seconds ago
|
|
job->setModificationTime(mtime);
|
|
job->setUiDelegate(nullptr);
|
|
connect(job, &KJob::result, this, &JobRemoteTest::slotResult);
|
|
connect(job, &KIO::TransferJob::dataReq, this, &JobRemoteTest::slotDataReq);
|
|
m_result = -1;
|
|
m_dataReqCount = 0;
|
|
enterLoop();
|
|
QVERIFY(m_result == 0); // no error
|
|
|
|
m_result = -1;
|
|
|
|
KIO::StoredTransferJob *getJob = KIO::storedGet(u, KIO::NoReload, KIO::HideProgressInfo);
|
|
getJob->setUiDelegate(nullptr);
|
|
connect(getJob, &KJob::result, this, &JobRemoteTest::slotGetResult);
|
|
enterLoop();
|
|
QCOMPARE(m_result, 0); // no error
|
|
QCOMPARE(m_data, QByteArray("This is a test for KIO::put()\n"));
|
|
// QCOMPARE( m_data.size(), 11 );
|
|
}
|
|
|
|
void JobRemoteTest::slotGetResult(KJob *job)
|
|
{
|
|
m_result = job->error();
|
|
m_data = static_cast<KIO::StoredTransferJob *>(job)->data();
|
|
Q_EMIT exitLoop();
|
|
}
|
|
|
|
void JobRemoteTest::slotDataReq(KIO::Job *, QByteArray &data)
|
|
{
|
|
// Really not the way you'd write a slotDataReq usually :)
|
|
switch (m_dataReqCount++) {
|
|
case 0:
|
|
data = "This is a test for ";
|
|
break;
|
|
case 1:
|
|
data = "KIO::put()\n";
|
|
break;
|
|
case 2:
|
|
data = QByteArray();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void JobRemoteTest::slotResult(KJob *job)
|
|
{
|
|
m_result = job->error();
|
|
Q_EMIT exitLoop();
|
|
}
|
|
|
|
////
|
|
|
|
void JobRemoteTest::openFileWriting()
|
|
{
|
|
m_rwCount = 0;
|
|
|
|
QUrl u(remoteTmpUrl());
|
|
u.setPath(u.path() + "openFileWriting");
|
|
fileJob = KIO::open(u, QIODevice::WriteOnly);
|
|
|
|
fileJob->setUiDelegate(nullptr);
|
|
connect(fileJob, &KJob::result, this, &JobRemoteTest::slotResult);
|
|
connect(fileJob, &KIO::FileJob::data, this, &JobRemoteTest::slotFileJobData);
|
|
connect(fileJob, &KIO::FileJob::open, this, &JobRemoteTest::slotFileJobOpen);
|
|
connect(fileJob, &KIO::FileJob::written, this, &JobRemoteTest::slotFileJobWritten);
|
|
connect(fileJob, &KIO::FileJob::position, this, &JobRemoteTest::slotFileJobPosition);
|
|
connect(fileJob, &KIO::FileJob::fileClosed, this, &JobRemoteTest::slotFileJobClose);
|
|
|
|
m_result = -1;
|
|
m_closeSignalCalled = false;
|
|
|
|
enterLoop();
|
|
QEXPECT_FAIL("", "Needs fixing in kio_file", Abort);
|
|
QVERIFY(m_result == 0); // no error
|
|
|
|
KIO::StoredTransferJob *getJob = KIO::storedGet(u, KIO::NoReload, KIO::HideProgressInfo);
|
|
getJob->setUiDelegate(nullptr);
|
|
connect(getJob, &KJob::result, this, &JobRemoteTest::slotGetResult);
|
|
enterLoop();
|
|
QCOMPARE(m_result, 0); // no error
|
|
QVERIFY(m_closeSignalCalled); // close signal called.
|
|
qDebug() << "m_data: " << m_data;
|
|
QCOMPARE(m_data, QByteArray("test....test....test....test....test....test....end"));
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJobData(KIO::Job *job, const QByteArray &data)
|
|
{
|
|
Q_UNUSED(job);
|
|
Q_UNUSED(data);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJobRedirection(KIO::Job *job, const QUrl &url)
|
|
{
|
|
Q_UNUSED(job);
|
|
Q_UNUSED(url);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJobMimetype(KIO::Job *job, const QString &type)
|
|
{
|
|
Q_UNUSED(job);
|
|
Q_UNUSED(type);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJobOpen(KIO::Job *job)
|
|
{
|
|
Q_UNUSED(job);
|
|
fileJob->seek(0);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJobWritten(KIO::Job *job, KIO::filesize_t written)
|
|
{
|
|
Q_UNUSED(job);
|
|
Q_UNUSED(written);
|
|
if (m_rwCount > 5) {
|
|
fileJob->close();
|
|
} else {
|
|
fileJob->seek(m_rwCount * 8);
|
|
m_rwCount++;
|
|
}
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJobPosition(KIO::Job *job, KIO::filesize_t offset)
|
|
{
|
|
Q_UNUSED(job);
|
|
Q_UNUSED(offset);
|
|
const QByteArray data("test....end");
|
|
fileJob->write(data);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJobClose(KIO::Job *job)
|
|
{
|
|
Q_UNUSED(job);
|
|
m_closeSignalCalled = true;
|
|
qDebug() << "+++++++++ filejob closed";
|
|
}
|
|
|
|
////
|
|
|
|
void JobRemoteTest::openFileReading()
|
|
{
|
|
QUrl u(remoteTmpUrl());
|
|
u.setPath(u.path() + "openFileReading");
|
|
|
|
const QByteArray putData("test1test2test3test4test5");
|
|
|
|
KIO::StoredTransferJob *putJob = KIO::storedPut(putData, u, 0600, KIO::Overwrite | KIO::HideProgressInfo);
|
|
|
|
quint64 secsSinceEpoch = QDateTime::currentSecsSinceEpoch(); // Use second granularity, supported on all filesystems
|
|
QDateTime mtime = QDateTime::fromSecsSinceEpoch(secsSinceEpoch - 30); // 30 seconds ago
|
|
putJob->setModificationTime(mtime);
|
|
putJob->setUiDelegate(nullptr);
|
|
connect(putJob, &KJob::result, this, &JobRemoteTest::slotResult);
|
|
m_result = -1;
|
|
enterLoop();
|
|
QVERIFY(m_result == 0); // no error
|
|
|
|
m_rwCount = 4;
|
|
m_data = QByteArray();
|
|
|
|
fileJob = KIO::open(u, QIODevice::ReadOnly);
|
|
|
|
fileJob->setUiDelegate(nullptr);
|
|
connect(fileJob, &KJob::result, this, &JobRemoteTest::slotResult);
|
|
connect(fileJob, &KIO::FileJob::data, this, &JobRemoteTest::slotFileJob2Data);
|
|
connect(fileJob, &KIO::FileJob::open, this, &JobRemoteTest::slotFileJob2Open);
|
|
connect(fileJob, &KIO::FileJob::written, this, &JobRemoteTest::slotFileJob2Written);
|
|
connect(fileJob, &KIO::FileJob::position, this, &JobRemoteTest::slotFileJob2Position);
|
|
|
|
// Can reuse this slot (same for all tests).
|
|
connect(fileJob, &KIO::FileJob::fileClosed, this, &JobRemoteTest::slotFileJobClose);
|
|
|
|
m_result = -1;
|
|
m_closeSignalCalled = false;
|
|
|
|
enterLoop();
|
|
QVERIFY(m_result == 0); // no error
|
|
QVERIFY(m_closeSignalCalled); // close signal called.
|
|
qDebug() << "resulting m_data: " << QString(m_data);
|
|
QCOMPARE(m_data, QByteArray("test5test4test3test2test1"));
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob2Data(KIO::Job *job, const QByteArray &data)
|
|
{
|
|
Q_UNUSED(job);
|
|
qDebug() << "m_rwCount = " << m_rwCount << " data: " << data;
|
|
m_data.append(data);
|
|
|
|
if (m_rwCount < 0) {
|
|
fileJob->close();
|
|
} else {
|
|
fileJob->seek(m_rwCount-- * 5);
|
|
}
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob2Redirection(KIO::Job *job, const QUrl &url)
|
|
{
|
|
Q_UNUSED(job);
|
|
Q_UNUSED(url);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob2Mimetype(KIO::Job *job, const QString &type)
|
|
{
|
|
Q_UNUSED(job);
|
|
qDebug() << "MIME type: " << type;
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob2Open(KIO::Job *job)
|
|
{
|
|
Q_UNUSED(job);
|
|
fileJob->seek(m_rwCount-- * 5);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob2Written(KIO::Job *job, KIO::filesize_t written)
|
|
{
|
|
Q_UNUSED(job);
|
|
Q_UNUSED(written);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob2Position(KIO::Job *job, KIO::filesize_t offset)
|
|
{
|
|
Q_UNUSED(job);
|
|
qDebug() << "position : " << offset << " -> read (5)";
|
|
fileJob->read(5);
|
|
}
|
|
|
|
////
|
|
|
|
void JobRemoteTest::slotMimetype(KIO::Job *job, const QString &type)
|
|
{
|
|
QVERIFY(job != nullptr);
|
|
m_mimetype = type;
|
|
}
|
|
|
|
void JobRemoteTest::openFileRead0Bytes()
|
|
{
|
|
QUrl u(remoteTmpUrl());
|
|
u.setPath(u.path() + "openFileReading");
|
|
|
|
const QByteArray putData("Doesn't matter");
|
|
|
|
KIO::StoredTransferJob *putJob = KIO::storedPut(putData, u, 0600, KIO::Overwrite | KIO::HideProgressInfo);
|
|
|
|
quint64 secsSinceEpoch = QDateTime::currentSecsSinceEpoch(); // Use second granularity, supported on all filesystems
|
|
QDateTime mtime = QDateTime::fromSecsSinceEpoch(secsSinceEpoch - 30); // 30 seconds ago
|
|
putJob->setModificationTime(mtime);
|
|
putJob->setUiDelegate(nullptr);
|
|
connect(putJob, &KJob::result, this, &JobRemoteTest::slotResult);
|
|
m_result = -1;
|
|
enterLoop();
|
|
QVERIFY(m_result == 0); // no error
|
|
|
|
m_data = QByteArray();
|
|
|
|
fileJob = KIO::open(u, QIODevice::ReadOnly);
|
|
|
|
fileJob->setUiDelegate(nullptr);
|
|
connect(fileJob, &KJob::result, this, &JobRemoteTest::slotResult);
|
|
connect(fileJob, &KIO::FileJob::data, this, &JobRemoteTest::slotFileJob3Data);
|
|
connect(fileJob, &KIO::FileJob::open, this, &JobRemoteTest::slotFileJob3Open);
|
|
// Can reuse this slot (it's a noop).
|
|
connect(fileJob, &KIO::FileJob::written, this, &JobRemoteTest::slotFileJob2Written);
|
|
connect(fileJob, &KIO::FileJob::position, this, &JobRemoteTest::slotFileJob3Position);
|
|
|
|
// Can reuse this as well.
|
|
connect(fileJob, &KIO::FileJob::fileClosed, this, &JobRemoteTest::slotFileJobClose);
|
|
|
|
m_result = -1;
|
|
m_closeSignalCalled = false;
|
|
|
|
enterLoop();
|
|
// Previously reading 0 bytes would cause both data() and error() being emitted...
|
|
QVERIFY(m_result == 0); // no error
|
|
QVERIFY(m_closeSignalCalled); // close signal called.
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob3Open(KIO::Job *job)
|
|
{
|
|
Q_UNUSED(job);
|
|
fileJob->seek(0);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob3Position(KIO::Job *job, KIO::filesize_t offset)
|
|
{
|
|
Q_UNUSED(job);
|
|
qDebug() << "position : " << offset << " -> read (0)";
|
|
fileJob->read(0);
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob3Data(KIO::Job *job, const QByteArray &data)
|
|
{
|
|
Q_UNUSED(job);
|
|
QVERIFY(data.isEmpty());
|
|
fileJob->close();
|
|
}
|
|
|
|
void JobRemoteTest::openFileTruncating()
|
|
{
|
|
QUrl u(remoteTmpUrl());
|
|
u.setPath(u.path() + "openFileTruncating");
|
|
|
|
const QByteArray putData("test1");
|
|
|
|
KIO::StoredTransferJob *putJob = KIO::storedPut(putData, u, 0600, KIO::Overwrite | KIO::HideProgressInfo);
|
|
|
|
quint64 secsSinceEpoch = QDateTime::currentSecsSinceEpoch(); // Use second granularity, supported on all filesystems
|
|
QDateTime mtime = QDateTime::fromSecsSinceEpoch(secsSinceEpoch - 30); // 30 seconds ago
|
|
putJob->setModificationTime(mtime);
|
|
putJob->setUiDelegate(nullptr);
|
|
connect(putJob, &KJob::result, this, &JobRemoteTest::slotResult);
|
|
m_result = -1;
|
|
enterLoop();
|
|
QVERIFY(m_result == 0); // no error
|
|
|
|
m_truncatedFile.setFileName(u.toLocalFile());
|
|
QVERIFY(m_truncatedFile.exists());
|
|
QVERIFY(m_truncatedFile.open(QIODevice::ReadOnly));
|
|
fileJob = KIO::open(u, QIODevice::ReadWrite);
|
|
|
|
fileJob->setUiDelegate(nullptr);
|
|
connect(fileJob, &KJob::result, this, &JobRemoteTest::slotResult);
|
|
connect(fileJob, &KIO::FileJob::open, this, &JobRemoteTest::slotFileJob4Open);
|
|
connect(fileJob, &KIO::FileJob::truncated, this, &JobRemoteTest::slotFileJob4Truncated);
|
|
|
|
// Can reuse this slot (same for all tests).
|
|
connect(fileJob, &KIO::FileJob::fileClosed, this, &JobRemoteTest::slotFileJobClose);
|
|
|
|
m_result = -1;
|
|
m_closeSignalCalled = false;
|
|
|
|
enterLoop();
|
|
QVERIFY(m_result == 0); // no error
|
|
QVERIFY(m_closeSignalCalled); // close signal called.
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob4Open(KIO::Job *job)
|
|
{
|
|
Q_UNUSED(job);
|
|
fileJob->truncate(10);
|
|
qDebug() << "Truncating file to 10";
|
|
}
|
|
|
|
void JobRemoteTest::slotFileJob4Truncated(KIO::Job *job, KIO::filesize_t length)
|
|
{
|
|
Q_UNUSED(job);
|
|
if (length == 10) {
|
|
m_truncatedFile.seek(0);
|
|
QCOMPARE(m_truncatedFile.readAll(), QByteArray("test1\x00\x00\x00\x00\x00", 10));
|
|
fileJob->truncate(4);
|
|
qDebug() << "Truncating file to 4";
|
|
} else if (length == 4) {
|
|
m_truncatedFile.seek(0);
|
|
QCOMPARE(m_truncatedFile.readAll(), QByteArray("test"));
|
|
fileJob->truncate(0);
|
|
qDebug() << "Truncating file to 0";
|
|
} else {
|
|
m_truncatedFile.seek(0);
|
|
QCOMPARE(m_truncatedFile.readAll(), QByteArray());
|
|
fileJob->close();
|
|
qDebug() << "Truncating file finished";
|
|
}
|
|
}
|
|
|
|
#include "moc_jobremotetest.cpp"
|