Warning, file /frameworks/kio/autotests/kfileitemtest.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2006 David Faure <faure@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "kfileitemtest.h" 0009 #include <QTest> 0010 #include <kfileitem.h> 0011 #include <kfileitemlistproperties.h> 0012 0013 #include "kiotesthelper.h" 0014 #include <KConfigGroup> 0015 #include <KDesktopFile> 0016 #include <KUser> 0017 #include <QTemporaryDir> 0018 #include <QTemporaryFile> 0019 0020 #include <KProtocolInfo> 0021 #include <QMimeDatabase> 0022 0023 QTEST_MAIN(KFileItemTest) 0024 0025 void KFileItemTest::initTestCase() 0026 { 0027 QStandardPaths::setTestModeEnabled(true); 0028 } 0029 0030 void KFileItemTest::testPermissionsString() 0031 { 0032 // Directory 0033 QTemporaryDir tempDir; 0034 KFileItem dirItem(QUrl::fromLocalFile(tempDir.path() + '/')); 0035 QCOMPARE((uint)dirItem.permissions(), (uint)0700); 0036 QCOMPARE(dirItem.permissionsString(), QStringLiteral("drwx------")); 0037 QVERIFY(dirItem.isReadable()); 0038 0039 // File 0040 QFile file(tempDir.path() + "/afile"); 0041 QVERIFY(file.open(QIODevice::WriteOnly)); 0042 file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadOther); // 0604 0043 KFileItem fileItem(QUrl::fromLocalFile(file.fileName()), QString(), KFileItem::Unknown); 0044 QCOMPARE((uint)fileItem.permissions(), (uint)0604); 0045 QCOMPARE(fileItem.permissionsString(), QStringLiteral("-rw----r--")); 0046 QVERIFY(fileItem.isReadable()); 0047 0048 // Symlink to file 0049 QString symlink = tempDir.path() + "/asymlink"; 0050 QVERIFY(file.link(symlink)); 0051 QUrl symlinkUrl = QUrl::fromLocalFile(symlink); 0052 KFileItem symlinkItem(symlinkUrl, QString(), KFileItem::Unknown); 0053 QCOMPARE((uint)symlinkItem.permissions(), (uint)0604); 0054 // This is a bit different from "ls -l": we get the 'l' but we see the permissions of the target. 0055 // This is actually useful though; the user sees it's a link, and can check if he can read the [target] file. 0056 QCOMPARE(symlinkItem.permissionsString(), QStringLiteral("lrw----r--")); 0057 QVERIFY(symlinkItem.isReadable()); 0058 0059 // Symlink to directory (#162544) 0060 QVERIFY(QFile::remove(symlink)); 0061 QVERIFY(QFile(tempDir.path() + '/').link(symlink)); 0062 KFileItem symlinkToDirItem(symlinkUrl, QString(), KFileItem::Unknown); 0063 QCOMPARE((uint)symlinkToDirItem.permissions(), (uint)0700); 0064 QCOMPARE(symlinkToDirItem.permissionsString(), QStringLiteral("lrwx------")); 0065 } 0066 0067 void KFileItemTest::testNull() 0068 { 0069 KFileItem null; 0070 QVERIFY(null.isNull()); 0071 KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/")), QString(), KFileItem::Unknown); 0072 QVERIFY(!fileItem.isNull()); 0073 null = fileItem; // ok, now 'null' isn't so null anymore 0074 QVERIFY(!null.isNull()); 0075 QVERIFY(null.isReadable()); 0076 QVERIFY(!null.isHidden()); 0077 } 0078 0079 void KFileItemTest::testDoesNotExist() 0080 { 0081 KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/doesnotexist")), QString(), KFileItem::Unknown); 0082 QVERIFY(!fileItem.isNull()); 0083 QVERIFY(!fileItem.isReadable()); 0084 QVERIFY(fileItem.user().isEmpty()); 0085 QVERIFY(fileItem.group().isEmpty()); 0086 } 0087 0088 void KFileItemTest::testDetach() 0089 { 0090 KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString(), KFileItem::Unknown); 0091 QCOMPARE(fileItem.name(), QStringLiteral("one")); 0092 KFileItem fileItem2(fileItem); 0093 QVERIFY(fileItem == fileItem2); 0094 QVERIFY(fileItem.d == fileItem2.d); 0095 fileItem2.setName(QStringLiteral("two")); 0096 QCOMPARE(fileItem2.name(), QStringLiteral("two")); 0097 QCOMPARE(fileItem.name(), QStringLiteral("one")); // it detached 0098 QVERIFY(fileItem == fileItem2); 0099 QVERIFY(fileItem.d != fileItem2.d); 0100 0101 fileItem = fileItem2; 0102 QCOMPARE(fileItem.name(), QStringLiteral("two")); 0103 QVERIFY(fileItem == fileItem2); 0104 QVERIFY(fileItem.d == fileItem2.d); 0105 QVERIFY(!(fileItem != fileItem2)); 0106 } 0107 0108 void KFileItemTest::testMove() 0109 { 0110 // Test move constructor 0111 { 0112 KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString(), KFileItem::Unknown); 0113 QCOMPARE(fileItem.name(), QStringLiteral("one")); 0114 KFileItem fileItem2(std::move(fileItem)); 0115 QCOMPARE(fileItem2.name(), QStringLiteral("one")); 0116 } 0117 0118 // Test move assignment 0119 { 0120 KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString(), KFileItem::Unknown); 0121 QCOMPARE(fileItem.name(), QStringLiteral("one")); 0122 KFileItem fileItem2(QUrl::fromLocalFile(QStringLiteral("/two")), QString(), KFileItem::Unknown); 0123 fileItem2 = std::move(fileItem); 0124 QCOMPARE(fileItem2.name(), QStringLiteral("one")); 0125 } 0126 0127 // Now to test some value changes to make sure moving works as intended. 0128 KFileItem fileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString(), KFileItem::Unknown); 0129 QCOMPARE(fileItem.name(), QStringLiteral("one")); 0130 fileItem.setUrl(QUrl::fromLocalFile(QStringLiteral("/two"))); 0131 QCOMPARE(fileItem.name(), QStringLiteral("two")); 0132 0133 // Move fileitem to fileItem2, it should now contain everything fileItem had. 0134 // Just testing a property to make sure it does. 0135 KFileItem fileItem2(std::move(fileItem)); 0136 QCOMPARE(fileItem2.name(), QStringLiteral("two")); 0137 } 0138 0139 void KFileItemTest::testMimeTypeCtor() 0140 { 0141 KFileItem fileItem; 0142 0143 fileItem = KFileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString("inode/directory")); 0144 QVERIFY(fileItem.isDir()); 0145 QVERIFY(fileItem.isMimeTypeKnown()); 0146 0147 fileItem = KFileItem(QUrl::fromLocalFile(QStringLiteral("/one")), QString("image/jpeg")); 0148 QVERIFY(!fileItem.isDir()); 0149 QVERIFY(fileItem.isMimeTypeKnown()); 0150 0151 fileItem = KFileItem(QUrl::fromLocalFile(QStringLiteral("/one.txt")), QString("inode/directory")); 0152 QVERIFY(fileItem.isDir()); 0153 QVERIFY(fileItem.isMimeTypeKnown()); 0154 0155 fileItem = KFileItem(QUrl::fromLocalFile(QStringLiteral("/one.txt")), QString(" ")); 0156 QVERIFY(!fileItem.isMimeTypeKnown()); 0157 } 0158 0159 void KFileItemTest::testBasic() 0160 { 0161 QTemporaryFile file; 0162 QVERIFY(file.open()); 0163 QFile fileObj(file.fileName()); 0164 QVERIFY(fileObj.open(QIODevice::WriteOnly)); 0165 fileObj.write(QByteArray("Hello")); 0166 fileObj.close(); 0167 0168 QUrl url = QUrl::fromLocalFile(file.fileName()); 0169 KFileItem fileItem(url, QString(), KFileItem::Unknown); 0170 QCOMPARE(fileItem.text(), url.fileName()); 0171 QVERIFY(fileItem.isLocalFile()); 0172 QCOMPARE(fileItem.localPath(), url.toLocalFile()); 0173 QCOMPARE(fileItem.size(), KIO::filesize_t(5)); 0174 QVERIFY(fileItem.linkDest().isEmpty()); 0175 QVERIFY(!fileItem.isHidden()); 0176 QVERIFY(fileItem.isReadable()); 0177 QVERIFY(fileItem.isWritable()); 0178 QVERIFY(fileItem.isFile()); 0179 QVERIFY(!fileItem.isDir()); 0180 QVERIFY(!fileItem.isDesktopFile()); 0181 #ifndef Q_OS_WIN 0182 QCOMPARE(fileItem.user(), KUser().loginName()); 0183 #endif 0184 } 0185 0186 void KFileItemTest::testRootDirectory() 0187 { 0188 const QString rootPath = QDir::rootPath(); 0189 QUrl url = QUrl::fromLocalFile(rootPath); 0190 KIO::UDSEntry entry; 0191 entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral(".")); 0192 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0193 KFileItem fileItem(entry, url); 0194 QCOMPARE(fileItem.text(), QStringLiteral(".")); 0195 QVERIFY(fileItem.isLocalFile()); 0196 QCOMPARE(fileItem.localPath(), url.toLocalFile()); 0197 QVERIFY(fileItem.linkDest().isEmpty()); 0198 QVERIFY(!fileItem.isHidden()); 0199 QVERIFY(!fileItem.isFile()); 0200 QVERIFY(fileItem.isDir()); 0201 QVERIFY(!fileItem.isDesktopFile()); 0202 } 0203 0204 void KFileItemTest::testHiddenFile() 0205 { 0206 QTemporaryDir tempDir; 0207 QFile file(tempDir.path() + "/.hiddenfile"); 0208 QVERIFY(file.open(QIODevice::WriteOnly)); 0209 KFileItem fileItem(QUrl::fromLocalFile(file.fileName()), QString(), KFileItem::Unknown); 0210 QCOMPARE(fileItem.text(), QStringLiteral(".hiddenfile")); 0211 QVERIFY(fileItem.isLocalFile()); 0212 QVERIFY(fileItem.isHidden()); 0213 } 0214 0215 void KFileItemTest::testMimeTypeOnDemand() 0216 { 0217 QTemporaryFile file; 0218 QVERIFY(file.open()); 0219 0220 { 0221 KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); 0222 fileItem.setDelayedMimeTypes(true); 0223 QVERIFY(fileItem.currentMimeType().isDefault()); 0224 QVERIFY(!fileItem.isMimeTypeKnown()); 0225 QVERIFY(!fileItem.isFinalIconKnown()); 0226 // qDebug() << fileItem.determineMimeType().name(); 0227 QCOMPARE(fileItem.determineMimeType().name(), QStringLiteral("application/x-zerosize")); 0228 QCOMPARE(fileItem.mimetype(), QStringLiteral("application/x-zerosize")); 0229 QVERIFY(fileItem.isMimeTypeKnown()); 0230 QVERIFY(fileItem.isFinalIconKnown()); 0231 } 0232 0233 { 0234 // Calling mimeType directly also does MIME type determination 0235 KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); 0236 fileItem.setDelayedMimeTypes(true); 0237 QVERIFY(!fileItem.isMimeTypeKnown()); 0238 QCOMPARE(fileItem.mimetype(), QStringLiteral("application/x-zerosize")); 0239 QVERIFY(fileItem.isMimeTypeKnown()); 0240 } 0241 0242 { 0243 // Calling overlays should NOT do MIME type determination (#237668) 0244 KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); 0245 fileItem.setDelayedMimeTypes(true); 0246 QVERIFY(!fileItem.isMimeTypeKnown()); 0247 fileItem.overlays(); 0248 QVERIFY(!fileItem.isMimeTypeKnown()); 0249 } 0250 0251 { 0252 QTemporaryFile file; 0253 QVERIFY(file.open()); 0254 // Check whether mime-magic is used. 0255 // No known extension, so it should be used by determineMimeType. 0256 file.write(QByteArray("%PDF-")); 0257 QString fileName = file.fileName(); 0258 QVERIFY(!fileName.isEmpty()); 0259 file.close(); 0260 KFileItem fileItem(QUrl::fromLocalFile(fileName)); 0261 fileItem.setDelayedMimeTypes(true); 0262 QCOMPARE(fileItem.currentMimeType().name(), QLatin1String("application/octet-stream")); 0263 QVERIFY(fileItem.currentMimeType().isValid()); 0264 QVERIFY(fileItem.currentMimeType().isDefault()); 0265 QVERIFY(!fileItem.isMimeTypeKnown()); 0266 QCOMPARE(fileItem.determineMimeType().name(), QStringLiteral("application/pdf")); 0267 QCOMPARE(fileItem.mimetype(), QStringLiteral("application/pdf")); 0268 } 0269 0270 { 0271 QTemporaryFile file(QDir::tempPath() + QLatin1String("/kfileitemtest_XXXXXX.txt")); 0272 QVERIFY(file.open()); 0273 // Check whether mime-magic is used. 0274 // Known extension, so it should NOT be used. 0275 file.write(QByteArray("<smil")); 0276 QString fileName = file.fileName(); 0277 QVERIFY(!fileName.isEmpty()); 0278 file.close(); 0279 KFileItem fileItem(QUrl::fromLocalFile(fileName)); 0280 fileItem.setDelayedMimeTypes(true); 0281 QCOMPARE(fileItem.currentMimeType().name(), QStringLiteral("text/plain")); 0282 QVERIFY(fileItem.isMimeTypeKnown()); 0283 QCOMPARE(fileItem.determineMimeType().name(), QStringLiteral("text/plain")); 0284 QCOMPARE(fileItem.mimetype(), QStringLiteral("text/plain")); 0285 0286 // And if the MIME type is not on demand? 0287 KFileItem fileItem2(QUrl::fromLocalFile(fileName)); 0288 QCOMPARE(fileItem2.currentMimeType().name(), QStringLiteral("text/plain")); // XDG says: application/smil; but can't sniff all files so this can't work 0289 QVERIFY(fileItem2.isMimeTypeKnown()); 0290 } 0291 } 0292 0293 void KFileItemTest::testCmp() 0294 { 0295 QTemporaryFile file; 0296 QVERIFY(file.open()); 0297 0298 KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); 0299 fileItem.setDelayedMimeTypes(true); 0300 KFileItem fileItem2(QUrl::fromLocalFile(file.fileName())); 0301 QVERIFY(fileItem == fileItem2); // created independently, but still 'equal' 0302 QVERIFY(fileItem.d != fileItem2.d); 0303 QVERIFY(!(fileItem != fileItem2)); 0304 QVERIFY(fileItem.cmp(fileItem2)); 0305 } 0306 0307 void KFileItemTest::testCmpAndInit() 0308 { 0309 QTemporaryDir tempDir; 0310 KFileItem dirItem(QUrl::fromLocalFile(tempDir.path())); 0311 QVERIFY(dirItem.isDir()); // this calls init() 0312 0313 KFileItem dirItem2(QUrl::fromLocalFile(tempDir.path())); 0314 // not yet init() called on dirItem2, but must be equal 0315 // compare init()ialized to un-init()ialized KFileItem 0316 QVERIFY(dirItem.cmp(dirItem2)); 0317 QVERIFY(dirItem2.isDir()); 0318 QVERIFY(dirItem.cmp(dirItem2)); 0319 QVERIFY(dirItem == dirItem2); 0320 QVERIFY(dirItem.d != dirItem2.d); 0321 QVERIFY(!(dirItem != dirItem2)); 0322 0323 // now the other way around, compare un-init()ialized to init()ialized KFileItem 0324 KFileItem dirItem3(QUrl::fromLocalFile(tempDir.path())); 0325 // not yet init() called on dirItem3, but must be equal 0326 QVERIFY(dirItem3.cmp(dirItem)); 0327 QVERIFY(dirItem3.isDir()); 0328 QVERIFY(dirItem3.cmp(dirItem)); 0329 QVERIFY(dirItem == dirItem3); 0330 QVERIFY(dirItem.d != dirItem3.d); 0331 QVERIFY(!(dirItem != dirItem3)); 0332 } 0333 0334 void KFileItemTest::testCmpByUrl() 0335 { 0336 const QUrl nulUrl; 0337 const QUrl url = QUrl::fromLocalFile(QStringLiteral("1foo")); 0338 const QUrl url2 = QUrl::fromLocalFile(QStringLiteral("fo1")); 0339 const QUrl url3 = QUrl::fromLocalFile(QStringLiteral("foo")); 0340 KFileItem nulFileItem; 0341 KFileItem nulFileItem2(nulUrl); 0342 KFileItem fileItem(url); 0343 KFileItem fileItem2(url2); 0344 KFileItem fileItem3(url3); 0345 0346 // an invalid KFileItem is considered equal to any other invalid KFileItem or invalid QUrl. 0347 QVERIFY(!(nulFileItem < nulFileItem)); 0348 QVERIFY(!(nulFileItem < nulFileItem2)); 0349 QVERIFY(!(nulFileItem2 < nulFileItem)); 0350 QVERIFY(!(nulFileItem < nulUrl)); 0351 // an invalid KFileItem is considered less than any valid KFileItem. 0352 QVERIFY(nulFileItem < fileItem); 0353 // a valid KFileItem is not less than an invalid KFileItem or invalid QUrl 0354 QVERIFY(!(fileItem < nulUrl)); 0355 QVERIFY(!(fileItem < nulFileItem)); 0356 QVERIFY(!(fileItem < nulFileItem2)); 0357 0358 QVERIFY(fileItem < fileItem2); 0359 QVERIFY(fileItem < url2); 0360 QVERIFY(!(fileItem2 < fileItem)); 0361 QVERIFY(fileItem2 < fileItem3); 0362 QVERIFY(fileItem < url3); 0363 QVERIFY(!(fileItem3 < fileItem2)); 0364 QVERIFY(!(fileItem3 < fileItem)); 0365 // Must be false as they are considered equal 0366 QVERIFY(!(fileItem < fileItem)); 0367 QVERIFY(!(fileItem < url)); 0368 } 0369 0370 void KFileItemTest::testRename() 0371 { 0372 KIO::UDSEntry entry; 0373 const QString origName = QStringLiteral("foo"); 0374 entry.fastInsert(KIO::UDSEntry::UDS_NAME, origName); 0375 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0376 KFileItem fileItem(entry, QUrl::fromLocalFile(QStringLiteral("/dir/foo"))); 0377 QCOMPARE(fileItem.name(), origName); 0378 QCOMPARE(fileItem.text(), origName); 0379 const QString newName = QStringLiteral("FiNeX_rocks"); 0380 fileItem.setName(newName); 0381 QCOMPARE(fileItem.name(), newName); 0382 QCOMPARE(fileItem.text(), newName); 0383 QCOMPARE(fileItem.entry().stringValue(KIO::UDSEntry::UDS_NAME), newName); // #195385 0384 } 0385 0386 void KFileItemTest::testRefresh() 0387 { 0388 QTemporaryDir tempDir; 0389 QFileInfo dirInfo(tempDir.path()); 0390 // Refresh on a dir 0391 KFileItem dirItem(QUrl::fromLocalFile(tempDir.path())); 0392 QVERIFY(dirItem.isDir()); 0393 QVERIFY(dirItem.entry().isDir()); 0394 QDateTime lastModified = dirInfo.lastModified(); 0395 // Qt 5.8 adds milliseconds (but UDSEntry has no support for that) 0396 lastModified = lastModified.addMSecs(-lastModified.time().msec()); 0397 QCOMPARE(dirItem.time(KFileItem::ModificationTime), lastModified); 0398 dirItem.refresh(); 0399 QVERIFY(dirItem.isDir()); 0400 QVERIFY(dirItem.entry().isDir()); 0401 QCOMPARE(dirItem.time(KFileItem::ModificationTime), lastModified); 0402 0403 // Refresh on a file 0404 QFile file(tempDir.path() + "/afile"); 0405 QVERIFY(file.open(QIODevice::WriteOnly)); 0406 file.write("Hello world\n"); 0407 file.close(); 0408 QFileInfo fileInfo(file.fileName()); 0409 const KIO::filesize_t expectedSize = 12; 0410 QCOMPARE(KIO::filesize_t(fileInfo.size()), expectedSize); 0411 file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadOther); // 0604 0412 KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); 0413 QVERIFY(fileItem.isFile()); 0414 QVERIFY(!fileItem.isLink()); 0415 QCOMPARE(fileItem.size(), expectedSize); 0416 #ifndef Q_OS_WIN 0417 QCOMPARE(fileItem.user(), KUser().loginName()); 0418 #endif 0419 // Qt 5.8 adds milliseconds (but UDSEntry has no support for that) 0420 lastModified = dirInfo.lastModified(); 0421 // Truncate away the milliseconds... 0422 lastModified = lastModified.addMSecs(-lastModified.time().msec()); 0423 // ...but it looks like the kernel rounds up when the msecs are .998 or .999, 0424 // so add a bit of tolerance 0425 auto expectedLastModified = lastModified; 0426 if (fileItem.time(KFileItem::ModificationTime) != lastModified && fileItem.time(KFileItem::ModificationTime) == lastModified.addSecs(1)) { 0427 expectedLastModified = expectedLastModified.addSecs(1); 0428 } 0429 QCOMPARE(fileItem.time(KFileItem::ModificationTime), expectedLastModified); 0430 fileItem.refresh(); 0431 QVERIFY(fileItem.isFile()); 0432 QVERIFY(!fileItem.isLink()); 0433 QCOMPARE(fileItem.size(), expectedSize); 0434 #ifndef Q_OS_WIN 0435 QCOMPARE(fileItem.user(), KUser().loginName()); 0436 #endif 0437 QCOMPARE(fileItem.time(KFileItem::ModificationTime), expectedLastModified); 0438 0439 // Refresh on a symlink to a file 0440 const QString symlink = tempDir.path() + "/asymlink"; 0441 QVERIFY(file.link(symlink)); 0442 QDateTime symlinkTime = QDateTime::currentDateTime().addSecs(-20); 0443 // we currently lose milliseconds.... 0444 symlinkTime = symlinkTime.addMSecs(-symlinkTime.time().msec()); 0445 setTimeStamp(symlink, symlinkTime); // differentiate link time and source file time 0446 const QUrl symlinkUrl = QUrl::fromLocalFile(symlink); 0447 KFileItem symlinkItem(symlinkUrl); 0448 QVERIFY(symlinkItem.isFile()); 0449 QVERIFY(symlinkItem.isLink()); 0450 QCOMPARE(symlinkItem.size(), expectedSize); 0451 QCOMPARE(symlinkItem.time(KFileItem::ModificationTime), symlinkTime); 0452 symlinkItem.refresh(); 0453 QVERIFY(symlinkItem.isFile()); 0454 QVERIFY(symlinkItem.isLink()); 0455 QCOMPARE(symlinkItem.size(), expectedSize); 0456 QCOMPARE(symlinkItem.time(KFileItem::ModificationTime), symlinkTime); 0457 0458 // Symlink to directory (#162544) 0459 QVERIFY(QFile::remove(symlink)); 0460 QVERIFY(QFile(tempDir.path() + '/').link(symlink)); 0461 KFileItem symlinkToDirItem(symlinkUrl); 0462 QVERIFY(symlinkToDirItem.isDir()); 0463 QVERIFY(symlinkToDirItem.isLink()); 0464 symlinkToDirItem.refresh(); 0465 QVERIFY(symlinkToDirItem.isDir()); 0466 QVERIFY(symlinkToDirItem.isLink()); 0467 } 0468 0469 void KFileItemTest::testDotDirectory() 0470 { 0471 QTemporaryDir tempDir; 0472 QFile file(tempDir.path() + "/.directory"); 0473 QVERIFY(file.open(QIODevice::WriteOnly)); 0474 file.write("[Desktop Entry]\nIcon=foo\nComment=com\n"); 0475 file.close(); 0476 { 0477 KFileItem fileItem(QUrl::fromLocalFile(tempDir.path() + '/'), QString(), KFileItem::Unknown); 0478 QVERIFY(fileItem.isLocalFile()); 0479 QCOMPARE(fileItem.mimeComment(), QStringLiteral("com")); 0480 QCOMPARE(fileItem.iconName(), QStringLiteral("foo")); 0481 } 0482 // Test for calling iconName first, to trigger MIME type resolution 0483 { 0484 KFileItem fileItem(QUrl::fromLocalFile(tempDir.path()), QString(), KFileItem::Unknown); 0485 QVERIFY(fileItem.isLocalFile()); 0486 QCOMPARE(fileItem.iconName(), QStringLiteral("foo")); 0487 } 0488 } 0489 0490 void KFileItemTest::testDecodeFileName_data() 0491 { 0492 QTest::addColumn<QString>("filename"); 0493 QTest::addColumn<QString>("expectedText"); 0494 0495 QTest::newRow("simple") << "filename" 0496 << "filename"; 0497 QTest::newRow("/ at end") << QString(QStringLiteral("foo") + QChar(0x2044)) << QString(QStringLiteral("foo") + QChar(0x2044)); 0498 QTest::newRow("/ at begin") << QString(QChar(0x2044)) << QString(QChar(0x2044)); 0499 } 0500 0501 void KFileItemTest::testDecodeFileName() 0502 { 0503 QFETCH(QString, filename); 0504 QFETCH(QString, expectedText); 0505 QCOMPARE(KIO::decodeFileName(filename), expectedText); 0506 } 0507 0508 void KFileItemTest::testEncodeFileName_data() 0509 { 0510 QTest::addColumn<QString>("text"); 0511 QTest::addColumn<QString>("expectedFileName"); 0512 0513 QTest::newRow("simple") << "filename" 0514 << "filename"; 0515 QTest::newRow("/ at end") << "foo/" << QString(QStringLiteral("foo") + QChar(0x2044)); 0516 QTest::newRow("/ at begin") << "/" << QString(QChar(0x2044)); 0517 } 0518 0519 void KFileItemTest::testEncodeFileName() 0520 { 0521 QFETCH(QString, text); 0522 QFETCH(QString, expectedFileName); 0523 QCOMPARE(KIO::encodeFileName(text), expectedFileName); 0524 } 0525 0526 void KFileItemTest::testListProperties_data() 0527 { 0528 QTest::addColumn<QString>("itemDescriptions"); 0529 QTest::addColumn<bool>("expectedReading"); 0530 QTest::addColumn<bool>("expectedDeleting"); 0531 QTest::addColumn<bool>("expectedIsLocal"); 0532 QTest::addColumn<bool>("expectedIsDirectory"); 0533 QTest::addColumn<bool>("expectedIsFile"); 0534 QTest::addColumn<QString>("expectedMimeType"); 0535 QTest::addColumn<QString>("expectedMimeGroup"); 0536 0537 /* clang-format off */ 0538 QTest::newRow("one file") << "f" << true << true << true << false << true << "text/plain" << "text"; 0539 QTest::newRow("one dir") << "d" << true << true << true << true << false << "inode/directory" << "inode"; 0540 QTest::newRow("root dir") << "/" << true << false << true << true << false << "inode/directory" << "inode"; 0541 QTest::newRow("file+dir") << "fd" << true << true << true << false << false << "" << ""; 0542 QTest::newRow("two dirs") << "dd" << true << true << true << true << false << "inode/directory" << "inode"; 0543 QTest::newRow("dir+root dir") << "d/" << true << false << true << true << false << "inode/directory" << "inode"; 0544 QTest::newRow("two (text+html) files") << "ff" << true << true << true << false << true << "" << "text"; 0545 QTest::newRow("three (text+html+empty) files") << "fff" << true << true << true << false << true << "" << ""; 0546 QTest::newRow("http url") << "h" << true << true /*says kio_http...*/ << false << false << true << "application/octet-stream" << "application"; 0547 QTest::newRow("2 http urls") << "hh" << true << true /*says kio_http...*/ << false << false << true << "application/octet-stream" << "application"; 0548 /* clang-format on */ 0549 } 0550 0551 void KFileItemTest::testListProperties() 0552 { 0553 QFETCH(QString, itemDescriptions); 0554 QFETCH(bool, expectedReading); 0555 QFETCH(bool, expectedDeleting); 0556 QFETCH(bool, expectedIsLocal); 0557 QFETCH(bool, expectedIsDirectory); 0558 QFETCH(bool, expectedIsFile); 0559 QFETCH(QString, expectedMimeType); 0560 QFETCH(QString, expectedMimeGroup); 0561 0562 QTemporaryDir tempDir; 0563 QDir baseDir(tempDir.path()); 0564 KFileItemList items; 0565 for (int i = 0; i < itemDescriptions.size(); ++i) { 0566 QString fileName = tempDir.path() + "/file" + QString::number(i); 0567 switch (itemDescriptions[i].toLatin1()) { 0568 case 'f': { 0569 if (i == 1) { // 2nd file is html 0570 fileName += QLatin1String(".html"); 0571 } 0572 QFile file(fileName); 0573 QVERIFY(file.open(QIODevice::WriteOnly)); 0574 if (i == 0) { 0575 file.write("Hello"); 0576 } else if (i == 1) { 0577 file.write("<html>"); 0578 } // i == 2: leave the file empty 0579 file.close(); 0580 KFileItem item(QUrl::fromLocalFile(fileName), QString(), KFileItem::Unknown); 0581 if (i == 0) { 0582 QCOMPARE(item.mimetype(), "text/plain"); 0583 } else if (i == 1) { 0584 QCOMPARE(item.mimetype(), "text/html"); 0585 } else if (i == 2) { 0586 QCOMPARE(item.mimetype(), "application/x-zerosize"); 0587 } 0588 items.push_back(std::move(item)); 0589 break; 0590 } 0591 case 'd': 0592 QVERIFY(baseDir.mkdir(fileName)); 0593 items << KFileItem(QUrl::fromLocalFile(fileName), QString(), KFileItem::Unknown); 0594 break; 0595 case '/': 0596 items << KFileItem(QUrl::fromLocalFile(QStringLiteral("/")), QString(), KFileItem::Unknown); 0597 break; 0598 case 'h': 0599 items << KFileItem(QUrl(QStringLiteral("http://www.kde.org")), QString(), KFileItem::Unknown); 0600 break; 0601 default: 0602 QVERIFY(false); 0603 } 0604 } 0605 KFileItemListProperties props(items); 0606 QCOMPARE(props.supportsReading(), expectedReading); 0607 QCOMPARE(props.supportsDeleting(), expectedDeleting); 0608 QCOMPARE(props.isLocal(), expectedIsLocal); 0609 QCOMPARE(props.isDirectory(), expectedIsDirectory); 0610 QCOMPARE(props.isFile(), expectedIsFile); 0611 QCOMPARE(props.mimeType(), expectedMimeType); 0612 QCOMPARE(props.mimeGroup(), expectedMimeGroup); 0613 } 0614 0615 void KFileItemTest::testIconNameForUrl_data() 0616 { 0617 QTest::addColumn<QUrl>("url"); 0618 QTest::addColumn<QString>("expectedIcon"); 0619 0620 QTest::newRow("root") << QUrl("file:/") << "inode-directory"; // the icon comes from KFileItem 0621 if (QFile::exists(QStringLiteral("/tmp"))) { 0622 QTest::newRow("subdir") << QUrl::fromLocalFile("/tmp") << "folder-temp"; 0623 } 0624 0625 QTest::newRow("home") << QUrl::fromLocalFile(QDir::homePath()) << "user-home"; 0626 const QString moviesPath = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).constFirst(); 0627 if (QFileInfo::exists(moviesPath)) { 0628 QTest::newRow("videos") << QUrl::fromLocalFile(moviesPath) << (moviesPath == QDir::homePath() ? "user-home" : "folder-videos"); 0629 } 0630 0631 QTest::newRow("empty") << QUrl() << "unknown"; 0632 QTest::newRow("relative") << QUrl("foo") << "unknown"; 0633 QTest::newRow("tilde") << QUrl("~") << "unknown"; 0634 0635 QTest::newRow("unknownscheme folder") << QUrl("unknownscheme:/") << "inode-directory"; 0636 QTest::newRow("unknownscheme file") << QUrl("unknownscheme:/test") << "application-octet-stream"; 0637 0638 QTest::newRow("trash:/ itself") << QUrl("trash:/") << "user-trash-full"; 0639 QTest::newRow("folder under trash:/") << QUrl("trash:/folder/") << "inode-directory"; 0640 QTest::newRow("file under trash:/") << QUrl("trash:/test") << "application-octet-stream"; 0641 QTest::newRow("image file under trash:/") << QUrl("trash:/test.png") << "image-png"; 0642 0643 QTest::newRow("https scheme") << QUrl("https://kde.org/") << "text-html"; 0644 0645 if (KProtocolInfo::isKnownProtocol("smb")) { 0646 QTest::newRow("smb root") << QUrl("smb:/") << "network-workgroup"; 0647 QTest::newRow("smb unknown file") << QUrl("smb:/test") << "network-workgroup"; 0648 QTest::newRow("smb directory/") << QUrl("smb:/unknown/") << "inode-directory"; 0649 QTest::newRow("smb image file") << QUrl("smb:/test.png") << "image-png"; 0650 } 0651 } 0652 0653 void KFileItemTest::testIconNameForUrl() 0654 { 0655 QFETCH(QUrl, url); 0656 QFETCH(QString, expectedIcon); 0657 0658 if (KIO::iconNameForUrl(url) != expectedIcon) { 0659 qDebug() << url; 0660 QCOMPARE(KIO::iconNameForUrl(url), expectedIcon); 0661 } 0662 } 0663 0664 void KFileItemTest::testMimetypeForRemoteFolder() 0665 { 0666 KIO::UDSEntry entry; 0667 entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("foo")); 0668 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0669 QUrl url(QStringLiteral("smb://remoteFolder/foo")); 0670 KFileItem fileItem(entry, url); 0671 0672 QCOMPARE(fileItem.mimetype(), QStringLiteral("inode/directory")); 0673 } 0674 0675 void KFileItemTest::testMimetypeForRemoteFolderWithFileType() 0676 { 0677 QString udsMimeType = QStringLiteral("application/x-smb-workgroup"); 0678 QVERIFY2(QMimeDatabase().mimeTypeForName(udsMimeType).isValid(), 0679 qPrintable(QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).join(':'))); // kcoreaddons installed? XDG_DATA_DIRS set? 0680 KIO::UDSEntry entry; 0681 entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("foo")); 0682 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0683 entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, udsMimeType); 0684 0685 QUrl url(QStringLiteral("smb://remoteFolder/foo")); 0686 KFileItem fileItem(entry, url); 0687 0688 QCOMPARE(fileItem.mimetype(), udsMimeType); 0689 } 0690 0691 void KFileItemTest::testCurrentMimetypeForRemoteFolder() 0692 { 0693 KIO::UDSEntry entry; 0694 entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("foo")); 0695 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0696 QUrl url(QStringLiteral("smb://remoteFolder/foo")); 0697 KFileItem fileItem(entry, url); 0698 0699 QCOMPARE(fileItem.currentMimeType().name(), QStringLiteral("inode/directory")); 0700 } 0701 0702 void KFileItemTest::testCurrentMimetypeForRemoteFolderWithFileType() 0703 { 0704 QString udsMimeType = QStringLiteral("application/x-smb-workgroup"); 0705 KIO::UDSEntry entry; 0706 entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("foo")); 0707 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0708 entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, udsMimeType); 0709 0710 QUrl url(QStringLiteral("smb://remoteFolder/foo")); 0711 KFileItem fileItem(entry, url); 0712 0713 QCOMPARE(fileItem.currentMimeType().name(), udsMimeType); 0714 } 0715 0716 void KFileItemTest::testIconNameForCustomFolderIcons() 0717 { 0718 // Custom folder icons should be displayed (bug 350612) 0719 0720 const QString iconName = QStringLiteral("folder-music"); 0721 0722 QTemporaryDir tempDir; 0723 const QUrl url = QUrl::fromLocalFile(tempDir.path()); 0724 KDesktopFile cfg(tempDir.path() + QLatin1String("/.directory")); 0725 cfg.desktopGroup().writeEntry("Icon", iconName); 0726 cfg.sync(); 0727 0728 KIO::UDSEntry entry; 0729 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0730 KFileItem fileItem(entry, url); 0731 0732 QCOMPARE(fileItem.iconName(), iconName); 0733 } 0734 0735 void KFileItemTest::testIconNameForStandardPath() 0736 { 0737 const QString iconName = QStringLiteral("folder-videos"); 0738 const QUrl url = QUrl::fromLocalFile(QDir::homePath() + QLatin1String("/Videos")); 0739 QStandardPaths::setTestModeEnabled(true); 0740 0741 KIO::UDSEntry entry; 0742 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0743 KFileItem fileItem(entry, url); 0744 0745 QCOMPARE(fileItem.iconName(), iconName); 0746 } 0747 0748 #ifndef Q_OS_WIN // user/group/other write permissions are not handled on windows 0749 0750 void KFileItemTest::testIsReadable_data() 0751 { 0752 QTest::addColumn<int>("mode"); 0753 QTest::addColumn<bool>("readable"); 0754 0755 QTest::newRow("fully-readable") << 0444 << true; 0756 QTest::newRow("user-readable") << 0400 << true; 0757 QTest::newRow("not-readable-by-us") << 0004 << false; 0758 QTest::newRow("not-readable-at-all") << 0000 << false; 0759 } 0760 0761 void KFileItemTest::testIsReadable() 0762 { 0763 QFETCH(int, mode); 0764 QFETCH(bool, readable); 0765 0766 QTemporaryFile file; 0767 QVERIFY(file.open()); 0768 int ret = fchmod(file.handle(), (mode_t)mode); 0769 QCOMPARE(ret, 0); 0770 0771 KFileItem fileItem(QUrl::fromLocalFile(file.fileName())); 0772 QCOMPARE(fileItem.isReadable(), readable); 0773 } 0774 0775 // Restore permissions so that the QTemporaryDir cleanup can happen (taken from tst_qsavefile.cpp) 0776 class PermissionRestorer 0777 { 0778 Q_DISABLE_COPY(PermissionRestorer) 0779 public: 0780 explicit PermissionRestorer(const QString &path) 0781 : m_path(path) 0782 { 0783 } 0784 ~PermissionRestorer() 0785 { 0786 restore(); 0787 } 0788 0789 inline void restore() 0790 { 0791 QFile file(m_path); 0792 #ifdef Q_OS_UNIX 0793 file.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)); 0794 #else 0795 file.setPermissions(QFile::WriteOwner); 0796 file.remove(); 0797 #endif 0798 } 0799 0800 private: 0801 const QString m_path; 0802 }; 0803 0804 void KFileItemTest::testNonWritableDirectory() 0805 { 0806 // Given a directory with a file in it 0807 QTemporaryDir dir; 0808 QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); 0809 QFile file(dir.path() + "/file1"); 0810 QVERIFY(file.open(QIODevice::WriteOnly)); 0811 QCOMPARE(file.write("Hello"), Q_INT64_C(5)); 0812 file.close(); 0813 // ... which is then made non-writable 0814 QVERIFY(QFile(dir.path()).setPermissions(QFile::ReadOwner | QFile::ExeOwner)); 0815 PermissionRestorer permissionRestorer(dir.path()); 0816 0817 // When using KFileItemListProperties on the file 0818 const KFileItem item(QUrl::fromLocalFile(file.fileName())); 0819 KFileItemListProperties props(KFileItemList{item}); 0820 0821 // Then it should say moving is not supported 0822 QVERIFY(!props.supportsMoving()); 0823 QVERIFY(props.supportsWriting()); // but we can write to the file itself 0824 } 0825 0826 #endif // Q_OS_WIN