diff --git a/autotests/kfileitemtest.cpp b/autotests/kfileitemtest.cpp index 0f4d33b8..14b5ed99 100644 --- a/autotests/kfileitemtest.cpp +++ b/autotests/kfileitemtest.cpp @@ -1,747 +1,755 @@ /* This file is part of the KDE project Copyright (C) 2006 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kfileitemtest.h" #include #include #include #include #include #include #include #include #include "kiotesthelper.h" #include QTEST_MAIN(KFileItemTest) void KFileItemTest::initTestCase() { } void KFileItemTest::testPermissionsString() { // Directory QTemporaryDir tempDir; KFileItem dirItem(QUrl::fromLocalFile(tempDir.path() + '/')); QCOMPARE((uint)dirItem.permissions(), (uint)0700); QCOMPARE(dirItem.permissionsString(), QStringLiteral("drwx------")); QVERIFY(dirItem.isReadable()); // File QFile file(tempDir.path() + "/afile"); QVERIFY(file.open(QIODevice::WriteOnly)); file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadOther); // 0604 KFileItem fileItem(QUrl::fromLocalFile(file.fileName()), QString(), KFileItem::Unknown); QCOMPARE((uint)fileItem.permissions(), (uint)0604); QCOMPARE(fileItem.permissionsString(), QStringLiteral("-rw----r--")); QVERIFY(fileItem.isReadable()); // Symlink to file QString symlink = tempDir.path() + "/asymlink"; QVERIFY(file.link(symlink)); QUrl symlinkUrl = QUrl::fromLocalFile(symlink); KFileItem symlinkItem(symlinkUrl, QString(), KFileItem::Unknown); QCOMPARE((uint)symlinkItem.permissions(), (uint)0604); // This is a bit different from "ls -l": we get the 'l' but we see the permissions of the target. // This is actually useful though; the user sees it's a link, and can check if he can read the [target] file. QCOMPARE(symlinkItem.permissionsString(), QStringLiteral("lrw----r--")); QVERIFY(symlinkItem.isReadable()); // Symlink to directory (#162544) QVERIFY(QFile::remove(symlink)); QVERIFY(QFile(tempDir.path() + '/').link(symlink)); KFileItem symlinkToDirItem(symlinkUrl, QString(), KFileItem::Unknown); QCOMPARE((uint)symlinkToDirItem.permissions(), (uint)0700); QCOMPARE(symlinkToDirItem.permissionsString(), QStringLiteral("lrwx------")); } void KFileItemTest::testNull() { KFileItem null; QVERIFY(null.isNull()); KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/")), QString(), KFileItem::Unknown); QVERIFY(!fileItem.isNull()); null = fileItem; // ok, now 'null' isn't so null anymore QVERIFY(!null.isNull()); QVERIFY(null.isReadable()); QVERIFY(!null.isHidden()); } void KFileItemTest::testDoesNotExist() { KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/doesnotexist")), QString(), KFileItem::Unknown); QVERIFY(!fileItem.isNull()); QVERIFY(!fileItem.isReadable()); QVERIFY(fileItem.user().isEmpty()); QVERIFY(fileItem.group().isEmpty()); } void KFileItemTest::testDetach() { KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString(), KFileItem::Unknown); QCOMPARE(fileItem.name(), QStringLiteral("one")); KFileItem fileItem2(fileItem); QVERIFY(fileItem == fileItem2); QVERIFY(fileItem.d == fileItem2.d); fileItem2.setName(QStringLiteral("two")); QCOMPARE(fileItem2.name(), QStringLiteral("two")); QCOMPARE(fileItem.name(), QStringLiteral("one")); // it detached QVERIFY(fileItem == fileItem2); QVERIFY(fileItem.d != fileItem2.d); fileItem = fileItem2; QCOMPARE(fileItem.name(), QStringLiteral("two")); QVERIFY(fileItem == fileItem2); QVERIFY(fileItem.d == fileItem2.d); QVERIFY(!(fileItem != fileItem2)); } void KFileItemTest::testMove() { // Test move constructor { KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString(), KFileItem::Unknown); QCOMPARE(fileItem.name(), QStringLiteral("one")); KFileItem fileItem2(std::move(fileItem)); QCOMPARE(fileItem2.name(), QStringLiteral("one")); } // Test move assignment { KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString(), KFileItem::Unknown); QCOMPARE(fileItem.name(), QStringLiteral("one")); KFileItem fileItem2(QUrl::fromLocalFile(QStringLiteral("/two")), QString(), KFileItem::Unknown); fileItem2 = std::move(fileItem); QCOMPARE(fileItem2.name(), QStringLiteral("one")); } // Now to test some value changes to make sure moving works as intended. KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString(), KFileItem::Unknown); QCOMPARE(fileItem.name(), QStringLiteral("one")); fileItem.setUrl(QUrl::fromLocalFile(QStringLiteral("/two"))); QCOMPARE(fileItem.name(), QStringLiteral("two")); // Move fileitem to fileItem2, it should now contain everything fileItem had. // Just testing a property to make sure it does. KFileItem fileItem2(std::move(fileItem)); QCOMPARE(fileItem2.name(), QStringLiteral("two")); } void KFileItemTest::testBasic() { QTemporaryFile file; QVERIFY(file.open()); QFile fileObj(file.fileName()); QVERIFY(fileObj.open(QIODevice::WriteOnly)); fileObj.write(QByteArray("Hello")); fileObj.close(); QUrl url = QUrl::fromLocalFile(file.fileName()); KFileItem fileItem(url, QString(), KFileItem::Unknown); QCOMPARE(fileItem.text(), url.fileName()); QVERIFY(fileItem.isLocalFile()); QCOMPARE(fileItem.localPath(), url.toLocalFile()); QCOMPARE(fileItem.size(), KIO::filesize_t(5)); QVERIFY(fileItem.linkDest().isEmpty()); QVERIFY(!fileItem.isHidden()); QVERIFY(fileItem.isReadable()); QVERIFY(fileItem.isWritable()); QVERIFY(fileItem.isFile()); QVERIFY(!fileItem.isDir()); QVERIFY(!fileItem.isDesktopFile()); #ifndef Q_OS_WIN QCOMPARE(fileItem.user(), KUser().loginName()); #endif } void KFileItemTest::testRootDirectory() { const QString rootPath = QDir::rootPath(); QUrl url = QUrl::fromLocalFile(rootPath); KIO::UDSEntry entry; entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral(".")); entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); KFileItem fileItem(entry, url); QCOMPARE(fileItem.text(), QStringLiteral(".")); QVERIFY(fileItem.isLocalFile()); QCOMPARE(fileItem.localPath(), url.toLocalFile()); QVERIFY(fileItem.linkDest().isEmpty()); QVERIFY(!fileItem.isHidden()); QVERIFY(!fileItem.isFile()); QVERIFY(fileItem.isDir()); QVERIFY(!fileItem.isDesktopFile()); } void KFileItemTest::testHiddenFile() { QTemporaryDir tempDir; QFile file(tempDir.path() + "/.hiddenfile"); QVERIFY(file.open(QIODevice::WriteOnly)); KFileItem fileItem(QUrl::fromLocalFile(file.fileName()), QString(), KFileItem::Unknown); QCOMPARE(fileItem.text(), QStringLiteral(".hiddenfile")); QVERIFY(fileItem.isLocalFile()); QVERIFY(fileItem.isHidden()); } void KFileItemTest::testMimeTypeOnDemand() { QTemporaryFile file; QVERIFY(file.open()); { KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); fileItem.setDelayedMimeTypes(true); QVERIFY(fileItem.currentMimeType().isDefault()); QVERIFY(!fileItem.isMimeTypeKnown()); QVERIFY(!fileItem.isFinalIconKnown()); //qDebug() << fileItem.determineMimeType().name(); QCOMPARE(fileItem.determineMimeType().name(), QStringLiteral("application/x-zerosize")); QCOMPARE(fileItem.mimetype(), QStringLiteral("application/x-zerosize")); QVERIFY(fileItem.isMimeTypeKnown()); QVERIFY(fileItem.isFinalIconKnown()); } { // Calling mimeType directly also does mimetype determination KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); fileItem.setDelayedMimeTypes(true); QVERIFY(!fileItem.isMimeTypeKnown()); QCOMPARE(fileItem.mimetype(), QStringLiteral("application/x-zerosize")); QVERIFY(fileItem.isMimeTypeKnown()); } { // Calling overlays should NOT do mimetype determination (#237668) KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); fileItem.setDelayedMimeTypes(true); QVERIFY(!fileItem.isMimeTypeKnown()); fileItem.overlays(); QVERIFY(!fileItem.isMimeTypeKnown()); } { QTemporaryFile file; QVERIFY(file.open()); // Check whether mime-magic is used. // No known extension, so it should be used by determineMimeType. file.write(QByteArray("%PDF-")); QString fileName = file.fileName(); QVERIFY(!fileName.isEmpty()); file.close(); KFileItem fileItem(QUrl::fromLocalFile(fileName)); fileItem.setDelayedMimeTypes(true); QCOMPARE(fileItem.currentMimeType().name(), QLatin1String("application/octet-stream")); QVERIFY(fileItem.currentMimeType().isValid()); QVERIFY(fileItem.currentMimeType().isDefault()); QVERIFY(!fileItem.isMimeTypeKnown()); QCOMPARE(fileItem.determineMimeType().name(), QStringLiteral("application/pdf")); QCOMPARE(fileItem.mimetype(), QStringLiteral("application/pdf")); } { QTemporaryFile file(QDir::tempPath() + QLatin1String("/kfileitemtest_XXXXXX.txt")); QVERIFY(file.open()); // Check whether mime-magic is used. // Known extension, so it should NOT be used. file.write(QByteArray("("filename"); QTest::addColumn("expectedText"); QTest::newRow("simple") << "filename" << "filename"; QTest::newRow("/ at end") << QString(QStringLiteral("foo") + QChar(0x2044)) << QString(QStringLiteral("foo") + QChar(0x2044)); QTest::newRow("/ at begin") << QString(QChar(0x2044)) << QString(QChar(0x2044)); } void KFileItemTest::testDecodeFileName() { QFETCH(QString, filename); QFETCH(QString, expectedText); QCOMPARE(KIO::decodeFileName(filename), expectedText); } void KFileItemTest::testEncodeFileName_data() { QTest::addColumn("text"); QTest::addColumn("expectedFileName"); QTest::newRow("simple") << "filename" << "filename"; QTest::newRow("/ at end") << "foo/" << QString(QStringLiteral("foo") + QChar(0x2044)); QTest::newRow("/ at begin") << "/" << QString(QChar(0x2044)); } void KFileItemTest::testEncodeFileName() { QFETCH(QString, text); QFETCH(QString, expectedFileName); QCOMPARE(KIO::encodeFileName(text), expectedFileName); } void KFileItemTest::testListProperties_data() { QTest::addColumn("itemDescriptions"); QTest::addColumn("expectedReading"); QTest::addColumn("expectedDeleting"); QTest::addColumn("expectedIsLocal"); QTest::addColumn("expectedIsDirectory"); QTest::addColumn("expectedIsFile"); QTest::addColumn("expectedMimeType"); QTest::addColumn("expectedMimeGroup"); QTest::newRow("one file") << "f" << true << true << true << false << true << "text/plain" << "text"; QTest::newRow("one dir") << "d" << true << true << true << true << false << "inode/directory" << "inode"; QTest::newRow("root dir") << "/" << true << false << true << true << false << "inode/directory" << "inode"; QTest::newRow("file+dir") << "fd" << true << true << true << false << false << "" << ""; QTest::newRow("two dirs") << "dd" << true << true << true << true << false << "inode/directory" << "inode"; QTest::newRow("dir+root dir") << "d/" << true << false << true << true << false << "inode/directory" << "inode"; QTest::newRow("two (text+html) files") << "ff" << true << true << true << false << true << "" << "text"; QTest::newRow("three (text+html+empty) files") << "fff" << true << true << true << false << true << "" << ""; QTest::newRow("http url") << "h" << true << true /*says kio_http...*/ << false << false << true << "application/octet-stream" << "application"; QTest::newRow("2 http urls") << "hh" << true << true /*says kio_http...*/ << false << false << true << "application/octet-stream" << "application"; } void KFileItemTest::testListProperties() { QFETCH(QString, itemDescriptions); QFETCH(bool, expectedReading); QFETCH(bool, expectedDeleting); QFETCH(bool, expectedIsLocal); QFETCH(bool, expectedIsDirectory); QFETCH(bool, expectedIsFile); QFETCH(QString, expectedMimeType); QFETCH(QString, expectedMimeGroup); QTemporaryDir tempDir; QDir baseDir(tempDir.path()); KFileItemList items; for (int i = 0; i < itemDescriptions.size(); ++i) { QString fileName = tempDir.path() + "/file" + QString::number(i); switch (itemDescriptions[i].toLatin1()) { case 'f': { if (i == 1) { // 2nd file is html fileName += QLatin1String(".html"); } QFile file(fileName); QVERIFY(file.open(QIODevice::WriteOnly)); if (i != 2) { // 3rd file is empty file.write("Hello"); } items << KFileItem(QUrl::fromLocalFile(fileName), QString(), KFileItem::Unknown); } break; case 'd': QVERIFY(baseDir.mkdir(fileName)); items << KFileItem(QUrl::fromLocalFile(fileName), QString(), KFileItem::Unknown); break; case '/': items << KFileItem(QUrl::fromLocalFile(QStringLiteral("/")), QString(), KFileItem::Unknown); break; case 'h': items << KFileItem(QUrl(QStringLiteral("http://www.kde.org")), QString(), KFileItem::Unknown); break; default: QVERIFY(false); } } KFileItemListProperties props(items); QCOMPARE(props.supportsReading(), expectedReading); QCOMPARE(props.supportsDeleting(), expectedDeleting); QCOMPARE(props.isLocal(), expectedIsLocal); QCOMPARE(props.isDirectory(), expectedIsDirectory); QCOMPARE(props.isFile(), expectedIsFile); QCOMPARE(props.mimeType(), expectedMimeType); QCOMPARE(props.mimeGroup(), expectedMimeGroup); } void KFileItemTest::testIconNameForUrl_data() { QTest::addColumn("url"); QTest::addColumn("expectedIcon"); QTest::newRow("root") << QUrl("file:/") << "folder"; // the icon comes from KProtocolInfo if (QFile::exists(QStringLiteral("/tmp"))) { QTest::newRow("subdir") << QUrl::fromLocalFile("/tmp") << "folder-temp"; } QTest::newRow("home") << QUrl::fromLocalFile(QDir::homePath()) << "user-home"; const QString moviesPath = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).first(); if (QFileInfo::exists(moviesPath)) { QTest::newRow("videos") << QUrl::fromLocalFile(moviesPath) << (moviesPath == QDir::homePath() ? "user-home" : "folder-videos"); } QTest::newRow("empty") << QUrl() << "unknown"; QTest::newRow("relative") << QUrl("foo") << "unknown"; QTest::newRow("tilde") << QUrl("~") << "unknown"; // TODO more tests } void KFileItemTest::testIconNameForUrl() { QFETCH(QUrl, url); QFETCH(QString, expectedIcon); if (KIO::iconNameForUrl(url) != expectedIcon) { qDebug() << url; QCOMPARE(KIO::iconNameForUrl(url), expectedIcon); } } void KFileItemTest::testMimetypeForRemoteFolder() { KIO::UDSEntry entry; entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("foo")); entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); QUrl url(QStringLiteral("smb://remoteFolder/foo")); KFileItem fileItem(entry, url); QCOMPARE(fileItem.mimetype(), QStringLiteral("inode/directory")); } void KFileItemTest::testMimetypeForRemoteFolderWithFileType() { QString udsMimeType = QStringLiteral("application/x-smb-workgroup"); QVERIFY2(QMimeDatabase().mimeTypeForName(udsMimeType).isValid(), qPrintable(QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).join(':'))); // kcoreaddons installed? XDG_DATA_DIRS set? KIO::UDSEntry entry; entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("foo")); entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, udsMimeType); QUrl url(QStringLiteral("smb://remoteFolder/foo")); KFileItem fileItem(entry, url); QCOMPARE(fileItem.mimetype(), udsMimeType); } void KFileItemTest::testCurrentMimetypeForRemoteFolder() { KIO::UDSEntry entry; entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("foo")); entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); QUrl url(QStringLiteral("smb://remoteFolder/foo")); KFileItem fileItem(entry, url); QCOMPARE(fileItem.currentMimeType().name(), QStringLiteral("inode/directory")); } void KFileItemTest::testCurrentMimetypeForRemoteFolderWithFileType() { QString udsMimeType = QStringLiteral("application/x-smb-workgroup"); KIO::UDSEntry entry; entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("foo")); entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, udsMimeType); QUrl url(QStringLiteral("smb://remoteFolder/foo")); KFileItem fileItem(entry, url); QCOMPARE(fileItem.currentMimeType().name(), udsMimeType); } void KFileItemTest::testIconNameForCustomFolderIcons() { // Custom folder icons should be displayed (bug 350612) const QString iconName = QStringLiteral("folder-music"); QTemporaryDir tempDir; const QUrl url = QUrl::fromLocalFile(tempDir.path()); KDesktopFile cfg(tempDir.path() + QLatin1String("/.directory")); cfg.desktopGroup().writeEntry("Icon", iconName); cfg.sync(); KIO::UDSEntry entry; entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); KFileItem fileItem(entry, url); QCOMPARE(fileItem.iconName(), iconName); } void KFileItemTest::testIconNameForStandardPath() { const QString iconName = QStringLiteral("folder-videos"); const QUrl url = QUrl::fromLocalFile(QDir::homePath() + QLatin1String("/Videos")); QStandardPaths::setTestModeEnabled(true); KIO::UDSEntry entry; entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); KFileItem fileItem(entry, url); QCOMPARE(fileItem.iconName(), iconName); } #ifndef Q_OS_WIN // user/group/other write permissions are not handled on windows void KFileItemTest::testIsReadable_data() { QTest::addColumn("mode"); QTest::addColumn("readable"); QTest::newRow("fully-readable") << 0444 << true; QTest::newRow("user-readable") << 0400 << true; QTest::newRow("not-readable-by-us") << 0004 << false; QTest::newRow("not-readable-at-all") << 0000 << false; } void KFileItemTest::testIsReadable() { QFETCH(int, mode); QFETCH(bool, readable); QTemporaryFile file; QVERIFY(file.open()); int ret = fchmod(file.handle(), (mode_t)mode); QCOMPARE(ret, 0); KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); QCOMPARE(fileItem.isReadable(), readable); } // Restore permissions so that the QTemporaryDir cleanup can happen (taken from tst_qsavefile.cpp) class PermissionRestorer { Q_DISABLE_COPY(PermissionRestorer) public: explicit PermissionRestorer(const QString& path) : m_path(path) {} ~PermissionRestorer() { restore(); } inline void restore() { QFile file(m_path); #ifdef Q_OS_UNIX file.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)); #else file.setPermissions(QFile::WriteOwner); file.remove(); #endif } private: const QString m_path; }; void KFileItemTest::testNonWritableDirectory() { // Given a directory with a file in it QTemporaryDir dir; QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); QFile file(dir.path() + "/file1"); QVERIFY(file.open(QIODevice::WriteOnly)); QCOMPARE(file.write("Hello"), Q_INT64_C(5)); file.close(); // ... which is then made non-writable QVERIFY(QFile(dir.path()).setPermissions(QFile::ReadOwner | QFile::ExeOwner)); PermissionRestorer permissionRestorer(dir.path()); // When using KFileItemListProperties on the file const KFileItem item(QUrl::fromLocalFile(file.fileName())); KFileItemListProperties props(KFileItemList() << item); // Then it should say moving is not supported QVERIFY(!props.supportsMoving()); QVERIFY(props.supportsWriting()); // but we can write to the file itself } #endif // Q_OS_WIN