File indexing completed on 2024-06-16 05:20:38
0001 /* 0002 SPDX-FileCopyrightText: 2016 Elvis Angelaccio <elvis.angelaccio@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "cliunarchivertest.h" 0008 #include "jobs.h" 0009 #include "testhelper.h" 0010 0011 #include <QDirIterator> 0012 #include <QFile> 0013 #include <QSignalSpy> 0014 #include <QTest> 0015 #include <QTextStream> 0016 0017 QTEST_GUILESS_MAIN(CliUnarchiverTest) 0018 0019 using namespace Kerfuffle; 0020 0021 void CliUnarchiverTest::initTestCase() 0022 { 0023 m_plugin = new Plugin(this); 0024 const auto plugins = m_pluginManger.availablePlugins(); 0025 for (Plugin *plugin : plugins) { 0026 if (plugin->metaData().pluginId() == QLatin1String("kerfuffle_cliunarchiver")) { 0027 m_plugin = plugin; 0028 return; 0029 } 0030 } 0031 } 0032 0033 void CliUnarchiverTest::testArchive_data() 0034 { 0035 QTest::addColumn<QString>("archivePath"); 0036 QTest::addColumn<QString>("expectedFileName"); 0037 QTest::addColumn<bool>("isReadOnly"); 0038 QTest::addColumn<bool>("isSingleFolder"); 0039 QTest::addColumn<Archive::EncryptionType>("expectedEncryptionType"); 0040 QTest::addColumn<QString>("expectedSubfolderName"); 0041 0042 QString archivePath = QFINDTESTDATA("data/one_toplevel_folder.rar"); 0043 QTest::newRow("RAR archive with one top-level folder") 0044 << archivePath << QFileInfo(archivePath).fileName() << true << true << Archive::Unencrypted << QStringLiteral("A"); 0045 0046 archivePath = QFINDTESTDATA("data/multiple_toplevel_entries.rar"); 0047 QTest::newRow("RAR archive with multiple top-level entries") 0048 << archivePath << QFileInfo(archivePath).fileName() << true << false << Archive::Unencrypted << QStringLiteral("multiple_toplevel_entries"); 0049 0050 archivePath = QFINDTESTDATA("data/encrypted_entries.rar"); 0051 QTest::newRow("RAR archive with encrypted entries") 0052 << archivePath << QFileInfo(archivePath).fileName() << true << true << Archive::Encrypted << QStringLiteral("A"); 0053 0054 archivePath = QFINDTESTDATA("data/one_toplevel_folder.lha"); 0055 QTest::newRow("LHA archive with one top-level folder") 0056 << archivePath << QFileInfo(archivePath).fileName() << true << true << Archive::Unencrypted << QStringLiteral("A"); 0057 0058 archivePath = QFINDTESTDATA("data/multiple_toplevel_entries.lha"); 0059 QTest::newRow("LHA archive with multiple top-level entries") 0060 << archivePath << QFileInfo(archivePath).fileName() << true << false << Archive::Unencrypted << QStringLiteral("multiple_toplevel_entries"); 0061 0062 archivePath = QFINDTESTDATA("data/test.sit"); 0063 QTest::newRow("stuffit archive unencrypted") << archivePath << QFileInfo(archivePath).fileName() << true << false << Archive::Unencrypted 0064 << QStringLiteral("test"); 0065 } 0066 0067 void CliUnarchiverTest::testArchive() 0068 { 0069 if (!m_plugin->isValid()) { 0070 QSKIP("cliunarchiver plugin not available. Skipping test.", SkipSingle); 0071 } 0072 0073 QFETCH(QString, archivePath); 0074 auto loadJob = Archive::load(archivePath, m_plugin, this); 0075 QVERIFY(loadJob); 0076 0077 TestHelper::startAndWaitForResult(loadJob); 0078 auto archive = loadJob->archive(); 0079 QVERIFY(archive); 0080 0081 if (!archive->isValid()) { 0082 QSKIP("Could not load the cliunarchiver plugin. Skipping test.", SkipSingle); 0083 } 0084 0085 QFETCH(QString, expectedFileName); 0086 QCOMPARE(QFileInfo(archive->fileName()).fileName(), expectedFileName); 0087 0088 QFETCH(bool, isReadOnly); 0089 QCOMPARE(archive->isReadOnly(), isReadOnly); 0090 0091 QFETCH(bool, isSingleFolder); 0092 QCOMPARE(archive->isSingleFolder(), isSingleFolder); 0093 0094 QFETCH(Archive::EncryptionType, expectedEncryptionType); 0095 QCOMPARE(archive->encryptionType(), expectedEncryptionType); 0096 0097 QFETCH(QString, expectedSubfolderName); 0098 QCOMPARE(archive->subfolderName(), expectedSubfolderName); 0099 } 0100 0101 void CliUnarchiverTest::testList_data() 0102 { 0103 QTest::addColumn<QString>("jsonFilePath"); 0104 QTest::addColumn<int>("expectedEntriesCount"); 0105 // Index of some entry to be tested. 0106 QTest::addColumn<int>("someEntryIndex"); 0107 // Entry metadata. 0108 QTest::addColumn<QString>("expectedName"); 0109 QTest::addColumn<bool>("isDirectory"); 0110 QTest::addColumn<bool>("isPasswordProtected"); 0111 QTest::addColumn<qulonglong>("expectedSize"); 0112 QTest::addColumn<qulonglong>("expectedCompressedSize"); 0113 QTest::addColumn<QString>("expectedTimestamp"); 0114 0115 QTest::newRow("archive with one top-level folder") << QFINDTESTDATA("data/one_toplevel_folder.json") << 9 << 6 << QStringLiteral("A/B/C/") << true << false 0116 << (qulonglong)0 << (qulonglong)0 << QStringLiteral("2015-12-21T16:57:20+01:00"); 0117 QTest::newRow("archive with multiple top-level entries") 0118 << QFINDTESTDATA("data/multiple_toplevel_entries.json") << 12 << 4 << QStringLiteral("data/A/B/test1.txt") << false << false << (qulonglong)7 0119 << (qulonglong)7 << QStringLiteral("2015-12-21T16:56:28+01:00"); 0120 QTest::newRow("archive with encrypted entries") << QFINDTESTDATA("data/encrypted_entries.json") << 9 << 5 << QStringLiteral("A/test1.txt") << false << true 0121 << (qulonglong)7 << (qulonglong)32 << QStringLiteral("2015-12-21T16:56:28+01:00"); 0122 QTest::newRow("huge archive") << QFINDTESTDATA("data/huge_archive.json") << 250 << 8 << QStringLiteral("PsycOPacK/Base Dictionnaries/att800") << false 0123 << false << (qulonglong)593687 << (qulonglong)225219 << QStringLiteral("2011-08-14T03:10:10+02:00"); 0124 } 0125 0126 void CliUnarchiverTest::testList() 0127 { 0128 qRegisterMetaType<Archive::Entry *>("Archive::Entry*"); 0129 CliPlugin *plugin = new CliPlugin(this, {QStringLiteral("dummy.rar"), QVariant::fromValue(m_plugin->metaData())}); 0130 QSignalSpy signalSpy(plugin, &CliPlugin::entry); 0131 0132 QFETCH(QString, jsonFilePath); 0133 QFETCH(int, expectedEntriesCount); 0134 0135 QFile jsonFile(jsonFilePath); 0136 QVERIFY(jsonFile.open(QIODevice::ReadOnly)); 0137 0138 QTextStream stream(&jsonFile); 0139 plugin->setJsonOutput(stream.readAll()); 0140 0141 QCOMPARE(signalSpy.count(), expectedEntriesCount); 0142 0143 QFETCH(int, someEntryIndex); 0144 QVERIFY(someEntryIndex < signalSpy.count()); 0145 Archive::Entry *entry = signalSpy.at(someEntryIndex).at(0).value<Archive::Entry *>(); 0146 0147 QFETCH(QString, expectedName); 0148 QCOMPARE(entry->fullPath(), expectedName); 0149 0150 QFETCH(bool, isDirectory); 0151 QCOMPARE(entry->isDir(), isDirectory); 0152 0153 QFETCH(bool, isPasswordProtected); 0154 QCOMPARE(entry->property("isPasswordProtected").toBool(), isPasswordProtected); 0155 0156 QFETCH(qulonglong, expectedSize); 0157 QCOMPARE(entry->property("size").toULongLong(), expectedSize); 0158 0159 QFETCH(qulonglong, expectedCompressedSize); 0160 QCOMPARE(entry->property("compressedSize").toULongLong(), expectedCompressedSize); 0161 0162 QFETCH(QString, expectedTimestamp); 0163 QEXPECT_FAIL("", "Something changed since Qt 5.11, needs investigation.", Continue); 0164 QCOMPARE(entry->property("timestamp").toString(), expectedTimestamp); 0165 0166 plugin->deleteLater(); 0167 } 0168 0169 void CliUnarchiverTest::testListArgs_data() 0170 { 0171 QTest::addColumn<QString>("archiveName"); 0172 QTest::addColumn<QString>("password"); 0173 QTest::addColumn<QStringList>("expectedArgs"); 0174 0175 QTest::newRow("unencrypted") << QStringLiteral("/tmp/foo.rar") << QString() << QStringList{QStringLiteral("-json"), QStringLiteral("/tmp/foo.rar")}; 0176 0177 QTest::newRow("header-encrypted") << QStringLiteral("/tmp/foo.rar") << QStringLiteral("1234") 0178 << QStringList{QStringLiteral("-json"), 0179 QStringLiteral("-password"), 0180 QStringLiteral("1234"), 0181 QStringLiteral("/tmp/foo.rar")}; 0182 } 0183 0184 void CliUnarchiverTest::testListArgs() 0185 { 0186 if (!m_plugin->isValid()) { 0187 QSKIP("cliunarchiver plugin not available. Skipping test.", SkipSingle); 0188 } 0189 0190 QFETCH(QString, archiveName); 0191 CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), QVariant::fromValue(m_plugin->metaData())}); 0192 QVERIFY(plugin); 0193 0194 QFETCH(QString, password); 0195 const auto replacedArgs = plugin->cliProperties()->listArgs(archiveName, password); 0196 0197 QFETCH(QStringList, expectedArgs); 0198 QCOMPARE(replacedArgs, expectedArgs); 0199 0200 plugin->deleteLater(); 0201 } 0202 0203 void CliUnarchiverTest::testExtraction_data() 0204 { 0205 QTest::addColumn<QString>("archivePath"); 0206 QTest::addColumn<QVector<Archive::Entry *>>("entriesToExtract"); 0207 QTest::addColumn<ExtractionOptions>("extractionOptions"); 0208 QTest::addColumn<int>("expectedExtractedEntriesCount"); 0209 0210 ExtractionOptions defaultOptions; 0211 defaultOptions.setAlwaysUseTempDir(true); 0212 0213 ExtractionOptions optionsNoPaths = defaultOptions; 0214 optionsNoPaths.setPreservePaths(false); 0215 0216 ExtractionOptions dragAndDropOptions = defaultOptions; 0217 dragAndDropOptions.setDragAndDropEnabled(true); 0218 0219 QTest::newRow("extract the whole multiple_toplevel_entries.rar") 0220 << QFINDTESTDATA("data/multiple_toplevel_entries.rar") << QVector<Archive::Entry *>() << defaultOptions << 12; 0221 0222 QTest::newRow("extract selected entries from a rar, without paths") 0223 << QFINDTESTDATA("data/one_toplevel_folder.rar") 0224 << QVector<Archive::Entry *>{new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A")), 0225 new Archive::Entry(this, QStringLiteral("A/B/test1.txt"), QStringLiteral("A/B"))} 0226 << optionsNoPaths << 2; 0227 0228 QTest::newRow("extract selected entries from a rar, preserve paths") 0229 << QFINDTESTDATA("data/one_toplevel_folder.rar") 0230 << (QVector<Archive::Entry *>{ 0231 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A")), 0232 new Archive::Entry(this, QStringLiteral("A/B/test1.txt"), QStringLiteral("A/B")), 0233 }) 0234 << defaultOptions << 4; 0235 0236 QTest::newRow("extract selected entries from a rar, drag-and-drop") 0237 << QFINDTESTDATA("data/one_toplevel_folder.rar") 0238 << (QVector<Archive::Entry *>{ 0239 new Archive::Entry(this, QStringLiteral("A/B/C/"), QStringLiteral("A/B/")), 0240 new Archive::Entry(this, QStringLiteral("A/test2.txt"), QStringLiteral("A/")), 0241 new Archive::Entry(this, QStringLiteral("A/B/C/test1.txt"), QStringLiteral("A/B/")), 0242 new Archive::Entry(this, QStringLiteral("A/B/C/test2.txt"), QStringLiteral("A/B/")), 0243 }) 0244 << dragAndDropOptions << 4; 0245 0246 QTest::newRow("rar with empty folders") << QFINDTESTDATA("data/empty_folders.rar") << QVector<Archive::Entry *>() << defaultOptions << 5; 0247 0248 QTest::newRow("rar with hidden folder and files") << QFINDTESTDATA("data/hidden_files.rar") << QVector<Archive::Entry *>() << defaultOptions << 4; 0249 } 0250 0251 // TODO: we can remove this test (which is duplicated from kerfuffle/archivetest) 0252 // if we ever ends up using a temp dir for any cliplugin, instead of only for cliunarchiver. 0253 void CliUnarchiverTest::testExtraction() 0254 { 0255 if (!m_plugin->isValid()) { 0256 QSKIP("cliunarchiver plugin not available. Skipping test.", SkipSingle); 0257 } 0258 0259 QFETCH(QString, archivePath); 0260 auto loadJob = Archive::load(archivePath, m_plugin, this); 0261 QVERIFY(loadJob); 0262 0263 TestHelper::startAndWaitForResult(loadJob); 0264 auto archive = loadJob->archive(); 0265 QVERIFY(archive); 0266 0267 if (!archive->isValid()) { 0268 QSKIP("Could not load the cliunarchiver plugin. Skipping test.", SkipSingle); 0269 } 0270 0271 QTemporaryDir destDir; 0272 if (!destDir.isValid()) { 0273 QSKIP("Could not create a temporary directory for extraction. Skipping test.", SkipSingle); 0274 } 0275 0276 QFETCH(QVector<Archive::Entry *>, entriesToExtract); 0277 QFETCH(ExtractionOptions, extractionOptions); 0278 auto extractionJob = archive->extractFiles(entriesToExtract, destDir.path(), extractionOptions); 0279 0280 QEventLoop eventLoop(this); 0281 connect(extractionJob, &KJob::result, &eventLoop, &QEventLoop::quit); 0282 extractionJob->start(); 0283 eventLoop.exec(); // krazy:exclude=crashy 0284 0285 QFETCH(int, expectedExtractedEntriesCount); 0286 int extractedEntriesCount = 0; 0287 0288 QDirIterator dirIt(destDir.path(), QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); 0289 while (dirIt.hasNext()) { 0290 extractedEntriesCount++; 0291 dirIt.next(); 0292 } 0293 0294 QCOMPARE(extractedEntriesCount, expectedExtractedEntriesCount); 0295 0296 archive->deleteLater(); 0297 } 0298 0299 void CliUnarchiverTest::testExtractArgs_data() 0300 { 0301 QTest::addColumn<QString>("archiveName"); 0302 QTest::addColumn<QVector<Archive::Entry *>>("files"); 0303 QTest::addColumn<QString>("password"); 0304 QTest::addColumn<QStringList>("expectedArgs"); 0305 0306 QTest::newRow("encrypted, multiple files") << QStringLiteral("/tmp/foo.rar") 0307 << QVector<Archive::Entry *>{new Archive::Entry(this, QStringLiteral("aDir/b.txt"), QStringLiteral("aDir")), 0308 new Archive::Entry(this, QStringLiteral("c.txt"), QString())} 0309 << QStringLiteral("1234") 0310 << QStringList{ 0311 QStringLiteral("-D"), 0312 QStringLiteral("-password"), 0313 QStringLiteral("1234"), 0314 QStringLiteral("/tmp/foo.rar"), 0315 QStringLiteral("aDir/b.txt"), 0316 QStringLiteral("c.txt"), 0317 }; 0318 0319 QTest::newRow("unencrypted, multiple files") << QStringLiteral("/tmp/foo.rar") 0320 << QVector<Archive::Entry *>{new Archive::Entry(this, QStringLiteral("aDir/b.txt"), QStringLiteral("aDir")), 0321 new Archive::Entry(this, QStringLiteral("c.txt"), QString())} 0322 << QString() 0323 << QStringList{ 0324 QStringLiteral("-D"), 0325 QStringLiteral("/tmp/foo.rar"), 0326 QStringLiteral("aDir/b.txt"), 0327 QStringLiteral("c.txt"), 0328 }; 0329 } 0330 0331 void CliUnarchiverTest::testExtractArgs() 0332 { 0333 if (!m_plugin->isValid()) { 0334 QSKIP("cliunarchiver plugin not available. Skipping test.", SkipSingle); 0335 } 0336 0337 QFETCH(QString, archiveName); 0338 CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), QVariant::fromValue(m_plugin->metaData())}); 0339 QVERIFY(plugin); 0340 0341 QFETCH(QVector<Archive::Entry *>, files); 0342 QStringList filesList; 0343 for (const Archive::Entry *e : std::as_const(files)) { 0344 filesList << e->fullPath(NoTrailingSlash); 0345 } 0346 0347 QFETCH(QString, password); 0348 0349 const auto replacedArgs = plugin->cliProperties()->extractArgs(archiveName, filesList, false, password); 0350 0351 QFETCH(QStringList, expectedArgs); 0352 QCOMPARE(replacedArgs, expectedArgs); 0353 0354 plugin->deleteLater(); 0355 } 0356 0357 #include "moc_cliunarchivertest.cpp"