File indexing completed on 2024-05-12 05:50:10
0001 /* 0002 SPDX-FileCopyrightText: 2010-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org> 0003 SPDX-FileCopyrightText: 2016 Elvis Angelaccio <elvis.angelaccio@kde.org> 0004 0005 SPDX-License-Identifier: BSD-2-Clause 0006 */ 0007 0008 #include "archive_kerfuffle.h" 0009 #include "jobs.h" 0010 #include "pluginmanager.h" 0011 #include "testhelper.h" 0012 0013 #include <KIO/Global> 0014 0015 #include <QDirIterator> 0016 #include <QMimeDatabase> 0017 #include <QStandardPaths> 0018 #include <QTest> 0019 0020 using namespace Kerfuffle; 0021 0022 class ExtractTest : public QObject 0023 { 0024 Q_OBJECT 0025 0026 private Q_SLOTS: 0027 void initTestCase(); 0028 void testExtraction_data(); 0029 void testExtraction(); 0030 void testPreservePermissions_data(); 0031 void testPreservePermissions(); 0032 0033 private: 0034 PluginManager m_pluginManager; 0035 QString m_expectedWorkingDir; 0036 }; 0037 0038 QTEST_GUILESS_MAIN(ExtractTest) 0039 0040 void ExtractTest::initTestCase() 0041 { 0042 // #395939: after each extraction, the cwd must be the one we started from. 0043 m_expectedWorkingDir = QDir::currentPath(); 0044 } 0045 0046 void ExtractTest::testExtraction_data() 0047 { 0048 QTest::addColumn<QString>("archivePath"); 0049 QTest::addColumn<QVector<Archive::Entry *>>("entriesToExtract"); 0050 QTest::addColumn<ExtractionOptions>("extractionOptions"); 0051 QTest::addColumn<int>("expectedExtractedEntriesCount"); 0052 0053 const auto setupRow = [](const char *name, 0054 const QString &archivePath, 0055 QVector<Archive::Entry *> entriesToExtract, 0056 ExtractionOptions extractionOptions, 0057 int expectedExtractedEntriesCount) { 0058 QTest::newRow(name) << archivePath << entriesToExtract << extractionOptions << expectedExtractedEntriesCount; 0059 }; 0060 0061 ExtractionOptions optionsPreservePaths; 0062 0063 ExtractionOptions optionsNoPaths; 0064 optionsNoPaths.setPreservePaths(false); 0065 0066 ExtractionOptions dragAndDropOptions; 0067 dragAndDropOptions.setDragAndDropEnabled(true); 0068 0069 QString archivePath = QFINDTESTDATA("data/simplearchive.tar.gz"); 0070 setupRow("extract the whole simplearchive.tar.gz", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 4); 0071 0072 archivePath = QFINDTESTDATA("data/simplearchive.tar.gz"); 0073 setupRow("extract selected entries from a tar.gz, without paths", 0074 archivePath, 0075 QVector<Archive::Entry *>{ 0076 new Archive::Entry(this, QStringLiteral("aDir/b.txt"), QStringLiteral("aDir")), 0077 new Archive::Entry(this, QStringLiteral("c.txt"), QString()), 0078 }, 0079 optionsNoPaths, 0080 2); 0081 0082 archivePath = QFINDTESTDATA("data/simplearchive.tar.gz"); 0083 setupRow("extract selected entries from a tar.gz, preserve paths", 0084 archivePath, 0085 QVector<Archive::Entry *>{ 0086 new Archive::Entry(this, QStringLiteral("aDir/b.txt"), QStringLiteral("aDir")), 0087 new Archive::Entry(this, QStringLiteral("c.txt"), QString()), 0088 }, 0089 optionsPreservePaths, 0090 3); 0091 0092 archivePath = QFINDTESTDATA("data/simplearchive.tar.gz"); 0093 setupRow("extract selected entries from a tar.gz, drag-and-drop", 0094 archivePath, 0095 QVector<Archive::Entry *>{ 0096 new Archive::Entry(this, QStringLiteral("c.txt"), QString()), 0097 new Archive::Entry(this, QStringLiteral("aDir/b.txt"), QStringLiteral("aDir/")), 0098 }, 0099 dragAndDropOptions, 0100 2); 0101 0102 archivePath = QFINDTESTDATA("data/one_toplevel_folder.zip"); 0103 setupRow("extract the whole one_toplevel_folder.zip", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 9); 0104 0105 archivePath = QFINDTESTDATA("data/one_toplevel_folder.zip"); 0106 setupRow("extract selected entries from a zip, without paths", 0107 archivePath, 0108 QVector<Archive::Entry *>{ 0109 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A")), 0110 new Archive::Entry(this, QStringLiteral("A/B/test1.txt"), QStringLiteral("A/B")), 0111 }, 0112 optionsNoPaths, 0113 2); 0114 0115 archivePath = QFINDTESTDATA("data/one_toplevel_folder.zip"); 0116 setupRow("extract selected entries from a zip, preserve paths", 0117 archivePath, 0118 QVector<Archive::Entry *>{ 0119 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A")), 0120 new Archive::Entry(this, QStringLiteral("A/B/test1.txt"), QStringLiteral("A/B")), 0121 }, 0122 optionsPreservePaths, 0123 4); 0124 0125 archivePath = QFINDTESTDATA("data/one_toplevel_folder.zip"); 0126 setupRow("extract selected entries from a zip, drag-and-drop", 0127 archivePath, 0128 QVector<Archive::Entry *>{ 0129 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A/")), 0130 new Archive::Entry(this, QStringLiteral("A/B/C/"), QStringLiteral("A/B/")), 0131 new Archive::Entry(this, QStringLiteral("A/B/C/test1.txt"), QStringLiteral("A/B/")), 0132 new Archive::Entry(this, QStringLiteral("A/B/C/test2.txt"), QStringLiteral("A/B/")), 0133 }, 0134 dragAndDropOptions, 0135 4); 0136 0137 archivePath = QFINDTESTDATA("data/one_toplevel_folder.7z"); 0138 setupRow("extract the whole one_toplevel_folder .7z", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 9); 0139 0140 archivePath = QFINDTESTDATA("data/one_toplevel_folder.7z"); 0141 setupRow("extract selected entries from a 7z, without paths", 0142 archivePath, 0143 QVector<Archive::Entry *>{ 0144 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A")), 0145 new Archive::Entry(this, QStringLiteral("A/B/test1.txt"), QStringLiteral("A/B")), 0146 }, 0147 optionsNoPaths, 0148 2); 0149 0150 archivePath = QFINDTESTDATA("data/one_toplevel_folder.7z"); 0151 setupRow("extract selected entries from a 7z, preserve paths", 0152 archivePath, 0153 QVector<Archive::Entry *>{ 0154 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A")), 0155 new Archive::Entry(this, QStringLiteral("A/B/test1.txt"), QStringLiteral("A/B")), 0156 }, 0157 optionsPreservePaths, 0158 4); 0159 0160 archivePath = QFINDTESTDATA("data/one_toplevel_folder.7z"); 0161 setupRow("extract selected entries from a 7z, drag-and-drop", 0162 archivePath, 0163 QVector<Archive::Entry *>{new Archive::Entry(this, QStringLiteral("A/B/test2.txt"), QStringLiteral("A/B/"))}, 0164 dragAndDropOptions, 0165 1); 0166 0167 archivePath = QFINDTESTDATA("data/empty_folders.zip"); 0168 setupRow("zip with empty folders", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 5); 0169 0170 archivePath = QFINDTESTDATA("data/empty_folders.tar.gz"); 0171 setupRow("tar with empty folders", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 5); 0172 0173 archivePath = QFINDTESTDATA("data/simplearchive.tar.bz2"); 0174 setupRow("extract selected entries from a bzip2-compressed tarball without path", 0175 archivePath, 0176 QVector<Archive::Entry *>{ 0177 new Archive::Entry(this, QStringLiteral("file3.txt"), QString()), 0178 new Archive::Entry(this, QStringLiteral("dir2/file22.txt"), QString()), 0179 }, 0180 optionsNoPaths, 0181 2); 0182 0183 archivePath = QFINDTESTDATA("data/simplearchive.tar.bz2"); 0184 setupRow("extract all entries from a bzip2 - compressed tarball with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0185 0186 archivePath = QFINDTESTDATA("data/simplearchive.tar.xz"); 0187 setupRow("extract selected entries from a xz-compressed tarball without path", 0188 archivePath, 0189 QVector<Archive::Entry *>{ 0190 new Archive::Entry(this, QStringLiteral("file3.txt"), QString()), 0191 new Archive::Entry(this, QStringLiteral("dir2/file22.txt"), QString()), 0192 }, 0193 optionsNoPaths, 0194 2); 0195 0196 archivePath = QFINDTESTDATA("data/simplearchive.tar.xz"); 0197 setupRow("extract all entries from a xz - compressed tarball with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0198 0199 archivePath = QFINDTESTDATA("data/simplearchive.tar.lzma"); 0200 setupRow("extract selected entries from a lzma-compressed tarball without path", 0201 archivePath, 0202 QVector<Archive::Entry *>{ 0203 new Archive::Entry(this, QStringLiteral("file3.txt"), QString()), 0204 new Archive::Entry(this, QStringLiteral("dir2/file22.txt"), QString()), 0205 }, 0206 optionsNoPaths, 0207 2); 0208 0209 archivePath = QFINDTESTDATA("data/simplearchive.tar.lzma"); 0210 setupRow("extract all entries from a lzma - compressed tarball with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0211 0212 archivePath = QFINDTESTDATA("data/simplearchive.tar.Z"); 0213 setupRow("extract selected entries from a compress (.Z)-compressed tarball without path", 0214 archivePath, 0215 QVector<Archive::Entry *>{ 0216 new Archive::Entry(this, QStringLiteral("file3.txt"), QString()), 0217 new Archive::Entry(this, QStringLiteral("dir2/file22.txt"), QString()), 0218 }, 0219 optionsNoPaths, 0220 2); 0221 0222 archivePath = QFINDTESTDATA("data/simplearchive.tar.Z"); 0223 setupRow("extract all entries from a compress (.Z)-compressed tarball with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0224 0225 archivePath = QFINDTESTDATA("data/simplearchive.tar.lz"); 0226 setupRow("extract selected entries from a lzipped tarball without path", 0227 archivePath, 0228 QVector<Archive::Entry *>{ 0229 new Archive::Entry(this, QStringLiteral("file3.txt"), QString()), 0230 new Archive::Entry(this, QStringLiteral("dir2/file22.txt"), QString()), 0231 }, 0232 optionsNoPaths, 0233 2); 0234 0235 archivePath = QFINDTESTDATA("data/simplearchive.tar.lz"); 0236 setupRow("extract all entries from a lzipped tarball with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0237 0238 // Only run tests for lzop compressed files if tar.lzo format is available 0239 if (PluginManager().supportedMimeTypes().contains(QLatin1String("application/x-tzo"))) { 0240 archivePath = QFINDTESTDATA("data/simplearchive.tar.lzo"); 0241 setupRow("extract selected entries from a lzop-compressed tarball without path", 0242 archivePath, 0243 QVector<Archive::Entry *>{ 0244 new Archive::Entry(this, QStringLiteral("file3.txt"), QString()), 0245 new Archive::Entry(this, QStringLiteral("dir2/file22.txt"), QString()), 0246 }, 0247 optionsNoPaths, 0248 2); 0249 0250 archivePath = QFINDTESTDATA("data/simplearchive.tar.lzo"); 0251 setupRow("extract all entries from a lzop - compressed tarball with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0252 0253 archivePath = QFINDTESTDATA("data/test.png.lzo"); 0254 setupRow("extract the single - file test.png.lzo", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0255 } 0256 0257 // Only run tests for lrzipped files if lrzip executable is found in path. 0258 if (!QStandardPaths::findExecutable(QStringLiteral("lrzip")).isEmpty()) { 0259 archivePath = QFINDTESTDATA("data/simplearchive.tar.lrz"); 0260 setupRow("extract selected entries from a lrzip-compressed tarball without path", 0261 archivePath, 0262 QVector<Archive::Entry *>{ 0263 new Archive::Entry(this, QStringLiteral("file3.txt"), QString()), 0264 new Archive::Entry(this, QStringLiteral("dir2/file22.txt"), QString()), 0265 }, 0266 optionsNoPaths, 0267 2); 0268 0269 archivePath = QFINDTESTDATA("data/simplearchive.tar.lrz"); 0270 setupRow("extract all entries from a lrzip - compressed tarball with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0271 0272 archivePath = QFINDTESTDATA("data/test.txt.lrz"); 0273 setupRow("extract the single - file test.txt.lrz", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0274 } else { 0275 qDebug() << "lrzip executable not found in path. Skipping lrzip test."; 0276 } 0277 0278 // Only run tests for zstd-compressed files if zstd executable is found in path. 0279 if (!QStandardPaths::findExecutable(QStringLiteral("zstd")).isEmpty()) { 0280 archivePath = QFINDTESTDATA("data/simplearchive.tar.zst"); 0281 setupRow("extract selected entries from a zstd-compressed tarball without path", 0282 archivePath, 0283 QVector<Archive::Entry *>{ 0284 new Archive::Entry(this, QStringLiteral("file3.txt"), QString()), 0285 new Archive::Entry(this, QStringLiteral("dir2/file22.txt"), QString()), 0286 }, 0287 optionsNoPaths, 0288 2); 0289 0290 archivePath = QFINDTESTDATA("data/simplearchive.tar.zst"); 0291 setupRow("extract all entries from a zst - compressed tarball with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0292 0293 archivePath = QFINDTESTDATA("data/test.txt.zst"); 0294 setupRow("extract the single - file test.txt.zst", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0295 } else { 0296 qDebug() << "zstd executable not found in path. Skipping zstd test."; 0297 } 0298 0299 // Only run tests for lz4-compressed files if lz4 executable is found in path. 0300 if (!QStandardPaths::findExecutable(QStringLiteral("lz4")).isEmpty()) { 0301 archivePath = QFINDTESTDATA("data/simplearchive.tar.lz4"); 0302 setupRow("extract selected entries from a lz4-compressed tarball without path", 0303 archivePath, 0304 QVector<Archive::Entry *>{ 0305 new Archive::Entry(this, QStringLiteral("file3.txt"), QString()), 0306 new Archive::Entry(this, QStringLiteral("dir2/file22.txt"), QString()), 0307 }, 0308 optionsNoPaths, 0309 2); 0310 0311 archivePath = QFINDTESTDATA("data/simplearchive.tar.lz4"); 0312 setupRow("extract all entries from a lz4 - compressed tarball with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0313 0314 archivePath = QFINDTESTDATA("data/test.txt.lz4"); 0315 setupRow("extract the single - file test.txt.lz4", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0316 } else { 0317 qDebug() << "lz4 executable not found in path. Skipping lz4 test."; 0318 } 0319 0320 archivePath = QFINDTESTDATA("data/simplearchive.xar"); 0321 setupRow("extract selected entries from a xar archive without path", 0322 archivePath, 0323 QVector<Archive::Entry *>{ 0324 new Archive::Entry(this, QStringLiteral("dir1/file11.txt"), QString()), 0325 new Archive::Entry(this, QStringLiteral("file4.txt"), QString()), 0326 }, 0327 optionsNoPaths, 0328 2); 0329 0330 archivePath = QFINDTESTDATA("data/simplearchive.xar"); 0331 setupRow("extract all entries from a xar archive with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 6); 0332 0333 archivePath = QFINDTESTDATA("data/hello-1.0-x86_64.AppImage"); 0334 setupRow("extract all entries from an AppImage with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 7); 0335 0336 archivePath = QFINDTESTDATA("data/hello-1.0-x86_64.AppImage"); 0337 setupRow("extract selected entries from an AppImage with path", 0338 archivePath, 0339 QVector<Archive::Entry *>{new Archive::Entry(this, QStringLiteral("usr/bin/hello"), QString())}, 0340 optionsPreservePaths, 0341 3); 0342 0343 archivePath = QFINDTESTDATA("data/archive-multivolume.7z.001"); 0344 setupRow("extract all entries from a multivolume 7z archive with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 3); 0345 0346 archivePath = QFINDTESTDATA("data/archive-multivolume.part1.rar"); 0347 setupRow("extract all entries from a multivolume rar archive with path", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 3); 0348 0349 archivePath = QFINDTESTDATA("data/firmware-pine64-20160329-6.1.aarch64.rpm"); 0350 setupRow("extract selected entries from rpm with path", 0351 archivePath, 0352 QVector<Archive::Entry *>{new Archive::Entry(this, QStringLiteral("boot/sunxi-spl.bin"), QString())}, 0353 optionsPreservePaths, 0354 2); 0355 0356 archivePath = QFINDTESTDATA("data/firmware-pine64-20160329-6.1.aarch64.rpm"); 0357 setupRow("#369535: broken drag-and-drop from rpm", 0358 archivePath, 0359 QVector<Archive::Entry *>{ 0360 new Archive::Entry(this, QStringLiteral("boot/sunxi-spl.bin"), QStringLiteral("boot/")), 0361 new Archive::Entry(this, QStringLiteral("boot/u-boot.img"), QStringLiteral("boot/")), 0362 }, 0363 dragAndDropOptions, 0364 2); 0365 0366 archivePath = QFINDTESTDATA("data/bug_#394542.zip"); 0367 setupRow("#394542: libzip doesn't extract selected folder", 0368 archivePath, 0369 QVector<Archive::Entry *>{ 0370 new Archive::Entry(this, QStringLiteral("2017 - 05/")), 0371 new Archive::Entry(this, QStringLiteral("2017 - 05/uffdå")), 0372 }, 0373 optionsPreservePaths, 0374 2); 0375 0376 archivePath = QFINDTESTDATA("data/one_toplevel_folder.arj"); 0377 setupRow("extract the whole one_toplevel_folder.arj", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 9); 0378 0379 archivePath = QFINDTESTDATA("data/one_toplevel_folder.arj"); 0380 setupRow("extract selected entries from a arj, without paths", 0381 archivePath, 0382 QVector<Archive::Entry *>{ 0383 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A")), 0384 new Archive::Entry(this, QStringLiteral("A/B/test1.txt"), QStringLiteral("A/B")), 0385 }, 0386 optionsNoPaths, 0387 2); 0388 0389 archivePath = QFINDTESTDATA("data/one_toplevel_folder.arj"); 0390 setupRow("extract selected entries from a arj, preserve paths", 0391 archivePath, 0392 QVector<Archive::Entry *>{ 0393 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A")), 0394 new Archive::Entry(this, QStringLiteral("A/B/test1.txt"), QStringLiteral("A/B")), 0395 }, 0396 optionsPreservePaths, 0397 4); 0398 0399 archivePath = QFINDTESTDATA("data/one_toplevel_folder.arj"); 0400 setupRow("extract selected entries from a arj, drag-and-drop", 0401 archivePath, 0402 QVector<Archive::Entry *>{ 0403 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A/")), 0404 new Archive::Entry(this, QStringLiteral("A/B/C/"), QStringLiteral("A/B/")), 0405 new Archive::Entry(this, QStringLiteral("A/B/C/test1.txt"), QStringLiteral("A/B/")), 0406 new Archive::Entry(this, QStringLiteral("A/B/C/test2.txt"), QStringLiteral("A/B/")), 0407 }, 0408 dragAndDropOptions, 0409 4); 0410 0411 archivePath = QFINDTESTDATA("data/test.z"); 0412 setupRow("extract the single - file test.z", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0413 0414 archivePath = QFINDTESTDATA("data/test.zz"); 0415 setupRow("extract the single - file test.zz", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0416 0417 archivePath = QFINDTESTDATA("data/test.txt.gz"); 0418 setupRow("extract the single - file test.txt.gz", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0419 0420 archivePath = QFINDTESTDATA("data/test.txt.bz2"); 0421 setupRow("extract the single - file test.txt.bz2", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0422 0423 archivePath = QFINDTESTDATA("data/test.png.lzma"); 0424 setupRow("extract the single - file test.png.lzma", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0425 0426 archivePath = QFINDTESTDATA("data/test.svgz"); 0427 setupRow("extract the single - file test.svgz", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0428 0429 archivePath = QFINDTESTDATA("data/test.sit"); 0430 setupRow("extract the whole test.sit", archivePath, QVector<Archive::Entry *>(), optionsPreservePaths, 1); 0431 0432 m_expectedWorkingDir = QDir::currentPath(); 0433 } 0434 0435 void ExtractTest::testExtraction() 0436 { 0437 QFETCH(QString, archivePath); 0438 auto loadJob = Archive::load(archivePath, this); 0439 QVERIFY(loadJob); 0440 loadJob->setAutoDelete(false); 0441 0442 TestHelper::startAndWaitForResult(loadJob); 0443 auto archive = loadJob->archive(); 0444 QVERIFY(archive); 0445 0446 if (!archive->isValid()) { 0447 QSKIP("Could not find a plugin to handle the archive. Skipping test.", SkipSingle); 0448 } 0449 0450 QTemporaryDir destDir; 0451 if (!destDir.isValid()) { 0452 QSKIP("Could not create a temporary directory for extraction. Skipping test.", SkipSingle); 0453 } 0454 0455 QFETCH(QVector<Archive::Entry *>, entriesToExtract); 0456 QFETCH(ExtractionOptions, extractionOptions); 0457 auto extractionJob = archive->extractFiles(entriesToExtract, destDir.path(), extractionOptions); 0458 QVERIFY(extractionJob); 0459 extractionJob->setAutoDelete(false); 0460 0461 TestHelper::startAndWaitForResult(extractionJob); 0462 0463 QFETCH(int, expectedExtractedEntriesCount); 0464 int extractedEntriesCount = 0; 0465 0466 QDirIterator dirIt(destDir.path(), QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); 0467 while (dirIt.hasNext()) { 0468 extractedEntriesCount++; 0469 dirIt.next(); 0470 } 0471 0472 QCOMPARE(extractedEntriesCount, expectedExtractedEntriesCount); 0473 QCOMPARE(QDir::currentPath(), m_expectedWorkingDir); 0474 0475 loadJob->deleteLater(); 0476 extractionJob->deleteLater(); 0477 archive->deleteLater(); 0478 } 0479 0480 void ExtractTest::testPreservePermissions_data() 0481 { 0482 QTest::addColumn<QString>("archiveName"); 0483 QTest::addColumn<Plugin *>("plugin"); 0484 QTest::addColumn<QString>("testFile"); 0485 QTest::addColumn<int>("expectedPermissions"); 0486 0487 // Repeat the same test case for each format and for each plugin supporting the format. 0488 const QStringList formats = TestHelper::testFormats(); 0489 for (const QString &format : formats) { 0490 const QString filename = QFINDTESTDATA(QStringLiteral("data/test_permissions.%1").arg(format)); 0491 const auto mime = QMimeDatabase().mimeTypeForFile(filename, QMimeDatabase::MatchExtension); 0492 const auto plugins = m_pluginManager.preferredWritePluginsFor(mime); 0493 for (const auto plugin : plugins) { 0494 QTest::newRow(QStringLiteral("test preserve 0755 permissions (%1, %2)").arg(format, plugin->metaData().pluginId()).toUtf8().constData()) 0495 << filename << plugin << QStringLiteral("0755.sh") << 0755; 0496 } 0497 } 0498 } 0499 0500 void ExtractTest::testPreservePermissions() 0501 { 0502 QFETCH(QString, archiveName); 0503 QFETCH(Plugin *, plugin); 0504 QVERIFY(plugin); 0505 auto loadJob = Archive::load(archiveName, plugin); 0506 QVERIFY(loadJob); 0507 loadJob->setAutoDelete(false); 0508 0509 TestHelper::startAndWaitForResult(loadJob); 0510 auto archive = loadJob->archive(); 0511 QVERIFY(archive); 0512 0513 if (!archive->isValid()) { 0514 QSKIP("Could not find a plugin to handle the archive. Skipping test.", SkipSingle); 0515 } 0516 0517 QTemporaryDir destDir; 0518 if (!destDir.isValid()) { 0519 QSKIP("Could not create a temporary directory for extraction. Skipping test.", SkipSingle); 0520 } 0521 0522 auto extractionJob = archive->extractFiles({}, destDir.path()); 0523 QVERIFY(extractionJob); 0524 extractionJob->setAutoDelete(false); 0525 TestHelper::startAndWaitForResult(extractionJob); 0526 0527 // Check whether extraction preserved the original permissions. 0528 QFETCH(QString, testFile); 0529 QFile file(QStringLiteral("%1/%2").arg(destDir.path(), testFile)); 0530 QVERIFY(file.exists()); 0531 QFETCH(int, expectedPermissions); 0532 const auto expectedQtPermissions = KIO::convertPermissions(expectedPermissions); 0533 // On Linux we get also the XXXUser flags which are ignored by KIO::convertPermissions(), 0534 // so we need to remove them before the comparison with the expected permissions. 0535 QCOMPARE(file.permissions() & expectedQtPermissions, expectedQtPermissions); 0536 0537 loadJob->deleteLater(); 0538 extractionJob->deleteLater(); 0539 archive->deleteLater(); 0540 } 0541 0542 #include "extracttest.moc"