File indexing completed on 2024-04-21 14:55:14

0001 /* This file is part of the KDE project
0002    Copyright (C) 2006 David Faure <faure@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 // This file can only be included once in a given binary
0021 
0022 #include <QDebug>
0023 #include <qglobal.h>
0024 #include <qstandardpaths.h>
0025 #include <qplatformdefs.h>
0026 #include <QDir>
0027 #include <QDateTime>
0028 #include <QTest>
0029 #ifdef Q_OS_UNIX
0030 #include <utime.h>
0031 #else
0032 #include <sys/utime.h>
0033 #endif
0034 #include <errno.h>
0035 #include <unistd.h>
0036 
0037 
0038 QString homeTmpDir()
0039 {
0040     const QString dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/kiotests/");
0041     if (!QFile::exists(dir)) {
0042         const bool ok = QDir().mkpath(dir);
0043         if (!ok) {
0044             qFatal("Couldn't create %s", qPrintable(dir));
0045         }
0046     }
0047     return dir;
0048 }
0049 
0050 QDateTime s_referenceTimeStamp;
0051 
0052 static void setTimeStamp(const QString &path, const QDateTime &mtime)
0053 {
0054 #ifdef Q_OS_UNIX
0055     // Put timestamp in the past so that we can check that the listing is correct
0056     struct utimbuf utbuf;
0057     utbuf.actime = mtime.toTime_t();
0058     utbuf.modtime = utbuf.actime;
0059     utime(QFile::encodeName(path), &utbuf);
0060     //qDebug( "Time changed for %s", qPrintable( path ) );
0061 #elif defined(Q_OS_WIN)
0062     struct _utimbuf utbuf;
0063     utbuf.actime = mtime.toTime_t();
0064     utbuf.modtime = utbuf.actime;
0065     _wutime(reinterpret_cast<const wchar_t *>(path.utf16()), &utbuf);
0066 #endif
0067 }
0068 
0069 static void createTestFile(const QString &path, bool plainText = false)
0070 {
0071     QFile f(path);
0072     if (!f.open(QIODevice::WriteOnly)) {
0073         qFatal("Couldn't create %s", qPrintable(path));
0074     }
0075     QByteArray data(plainText ? "Hello world" : "Hello\0world", 11);
0076     QCOMPARE(data.size(), 11);
0077     f.write(data);
0078     f.close();
0079     setTimeStamp(path, s_referenceTimeStamp);
0080 }
0081 
0082 static void createTestSymlink(const QString &path, const QByteArray &target = "/IDontExist")
0083 {
0084     QFile::remove(path);
0085     bool ok = symlink(target.constData(), QFile::encodeName(path)) == 0;     // broken symlink
0086     if (!ok) {
0087         qFatal("couldn't create symlink: %s", strerror(errno));
0088     }
0089     QT_STATBUF buf;
0090 #ifndef Q_OS_WIN
0091     QVERIFY(QT_LSTAT(QFile::encodeName(path), &buf) == 0);
0092 #endif
0093     QVERIFY((buf.st_mode & QT_STAT_MASK) == QT_STAT_LNK);
0094     //qDebug( "symlink %s created", qPrintable( path ) );
0095     QVERIFY(QFileInfo(path).isSymLink());
0096 }
0097 
0098 enum CreateTestDirectoryOptions { DefaultOptions = 0, NoSymlink = 1 };
0099 static void createTestDirectory(const QString &path, CreateTestDirectoryOptions opt = DefaultOptions)
0100 {
0101     QDir dir;
0102     bool ok = dir.mkdir(path);
0103     if (!ok && !dir.exists()) {
0104         qFatal("Couldn't create %s", qPrintable(path));
0105     }
0106     createTestFile(path + "/testfile");
0107     if ((opt & NoSymlink) == 0) {
0108 #ifndef Q_OS_WIN
0109         createTestSymlink(path + "/testlink");
0110         QVERIFY(QFileInfo(path + "/testlink").isSymLink());
0111 #else
0112         // to not change the filecount everywhere in the tests
0113         createTestFile(path + "/testlink");
0114 #endif
0115     }
0116     setTimeStamp(path, s_referenceTimeStamp);
0117 }
0118 
0119 #include <kio/jobuidelegateextension.h>
0120 class PredefinedAnswerJobUiDelegate : public KIO::JobUiDelegateExtension
0121 {
0122 public:
0123     PredefinedAnswerJobUiDelegate()
0124         : JobUiDelegateExtension(),
0125           m_askFileRenameCalled(0),
0126           m_askSkipCalled(0),
0127           m_askDeleteCalled(0),
0128           m_messageBoxCalled(0),
0129           m_renameResult(KIO::R_SKIP),
0130           m_skipResult(KIO::S_SKIP),
0131           m_deleteResult(false),
0132           m_messageBoxResult(0)
0133     {
0134     }
0135 
0136     KIO::RenameDialog_Result askFileRename(KJob *job,
0137                                            const QString &caption,
0138                                            const QUrl &src,
0139                                            const QUrl &dest,
0140                                            KIO::RenameDialog_Options options,
0141                                            QString &newDest,
0142                                            KIO::filesize_t = (KIO::filesize_t) - 1,
0143                                            KIO::filesize_t = (KIO::filesize_t) - 1,
0144                                            const QDateTime  & = QDateTime(),
0145                                            const QDateTime  & = QDateTime(),
0146                                            const QDateTime  & = QDateTime(),
0147                                            const QDateTime  & = QDateTime()) override {
0148         Q_UNUSED(job)
0149         Q_UNUSED(caption)
0150         Q_UNUSED(src)
0151         Q_UNUSED(dest)
0152         Q_UNUSED(options)
0153         Q_UNUSED(newDest)
0154         ++m_askFileRenameCalled;
0155         return m_renameResult;
0156     }
0157 
0158     KIO::SkipDialog_Result askSkip(KJob *job,
0159                                    KIO::SkipDialog_Options options,
0160                                    const QString &error_text) override {
0161         Q_UNUSED(job)
0162         Q_UNUSED(options)
0163         Q_UNUSED(error_text)
0164         ++m_askSkipCalled;
0165         return m_skipResult;
0166     }
0167 
0168     bool askDeleteConfirmation(const QList<QUrl> &urls, DeletionType deletionType,
0169                                ConfirmationType confirmationType) override {
0170         Q_UNUSED(urls);
0171         Q_UNUSED(deletionType);
0172         Q_UNUSED(confirmationType);
0173         ++m_askDeleteCalled;
0174         return m_deleteResult;
0175     }
0176 
0177     int requestMessageBox(MessageBoxType type, const QString &text,
0178                           const QString &caption,
0179                           const QString &buttonYes,
0180                           const QString &buttonNo,
0181                           const QString &iconYes = QString(),
0182                           const QString &iconNo = QString(),
0183                           const QString &dontAskAgainName = QString(),
0184                           const KIO::MetaData &sslMetaData = KIO::MetaData()) override
0185     {
0186         Q_UNUSED(type);
0187         Q_UNUSED(text);
0188         Q_UNUSED(caption);
0189         Q_UNUSED(buttonYes);
0190         Q_UNUSED(buttonNo);
0191         Q_UNUSED(iconYes);
0192         Q_UNUSED(iconNo);
0193         Q_UNUSED(dontAskAgainName);
0194         Q_UNUSED(sslMetaData);
0195         ++m_messageBoxCalled;
0196         return m_messageBoxResult;
0197     }
0198 
0199     // yeah, public, for get and reset.
0200     int m_askFileRenameCalled;
0201     int m_askSkipCalled;
0202     int m_askDeleteCalled;
0203     int m_messageBoxCalled;
0204 
0205     KIO::RenameDialog_Result m_renameResult;
0206     KIO::SkipDialog_Result m_skipResult;
0207     bool m_deleteResult;
0208     int m_messageBoxResult;
0209 };