File indexing completed on 2024-05-12 05:50:11

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 <QStandardPaths>
0014 #include <QTest>
0015 
0016 using namespace Kerfuffle;
0017 
0018 class LoadTest : public QObject
0019 {
0020     Q_OBJECT
0021 
0022 private Q_SLOTS:
0023     void testProperties_data();
0024     void testProperties();
0025 };
0026 
0027 QTEST_GUILESS_MAIN(LoadTest)
0028 
0029 void LoadTest::testProperties_data()
0030 {
0031     QTest::addColumn<QString>("archivePath");
0032     QTest::addColumn<QString>("expectedBaseName");
0033     QTest::addColumn<bool>("isReadOnly");
0034     QTest::addColumn<bool>("canFallbackOnReadOnly");
0035     QTest::addColumn<bool>("isSingleFile");
0036     QTest::addColumn<bool>("isSingleFolder");
0037     QTest::addColumn<bool>("isMultiVolume");
0038     QTest::addColumn<int>("numberOfVolumes");
0039     QTest::addColumn<Archive::EncryptionType>("expectedEncryptionType");
0040     QTest::addColumn<int>("numberOfEntries");
0041     QTest::addColumn<QString>("expectedSubfolderName");
0042     QTest::addColumn<QString>("expectedComment");
0043 
0044     // Test non-existent tar archive.
0045     QTest::newRow("non-existent tar archive") << QStringLiteral("/tmp/foo.tar.gz") << QStringLiteral("foo") << false << false << false << false << false << 0
0046                                               << Archive::Unencrypted << 0 << QString() << QString();
0047 
0048     // Test non-archive file
0049     QTest::newRow("not an archive") << QStringLiteral("/tmp/foo.pdf") << QString() << false << false << false << false << false << 0 << Archive::Unencrypted
0050                                     << 0 << QString() << QString();
0051 
0052     // Test dummy source code tarball.
0053     QTest::newRow("dummy source code tarball") << QFINDTESTDATA("data/code-x.y.z.tar.gz") << QStringLiteral("code-x.y.z") << false << false << false << true
0054                                                << false << 0 << Archive::Unencrypted << 3 << QStringLiteral("awesome_project") << QString();
0055 
0056     QTest::newRow("simple compressed tar archive") << QFINDTESTDATA("data/simplearchive.tar.gz") << QStringLiteral("simplearchive") << false << false << false
0057                                                    << false << false << 0 << Archive::Unencrypted << 4 << QStringLiteral("simplearchive") << QString();
0058 
0059     QTest::newRow("simple C++ static library") << QFINDTESTDATA("data/libdummy.a")
0060                                                << QStringLiteral("libdummy")
0061                                                // NOTE: there are 2 objects in this library, but libarchive also reports the "archive symbol table"
0062                                                // as a separate entry with path "/", which is then skipped by the ArchiveModel.
0063                                                << true << false << false << false << false << 0 << Archive::Unencrypted << 2 + 1 << QStringLiteral("libdummy")
0064                                                << QString();
0065 
0066     QTest::newRow("encrypted zip, single entry") << QFINDTESTDATA("data/archivetest_encrypted.zip") << QStringLiteral("archivetest_encrypted") << false << true
0067                                                  << true << false << false << 0 << Archive::Encrypted << 1 << QStringLiteral("archivetest_encrypted")
0068                                                  << QString();
0069 
0070     QTest::newRow("simple zip, one unencrypted entry")
0071         << QFINDTESTDATA("data/archivetest_unencrypted.zip") << QStringLiteral("archivetest_unencrypted") << false << true << true << false << false << 0
0072         << Archive::Unencrypted << 1 << QStringLiteral("archivetest_unencrypted") << QString();
0073 
0074     QTest::newRow("rpm archive, no single folder")
0075         << QFINDTESTDATA("data/wget.rpm")
0076         << QStringLiteral("wget")
0077         // NOTE: there are 49 files in this RPM, but for some reason libarchive reports "./usr/share/doc/wget" as separate entry...
0078         << true << false << false << false << false << 0 << Archive::Unencrypted << 49 + 1 << QStringLiteral("wget") << QString();
0079 
0080     QTest::newRow("bzip2-compressed tarball") << QFINDTESTDATA("data/simplearchive.tar.bz2") << QStringLiteral("simplearchive") << false << false << false
0081                                               << false << false << 0 << Archive::Unencrypted << 5 << QStringLiteral("simplearchive") << QString();
0082 
0083     QTest::newRow("xz-compressed tarball") << QFINDTESTDATA("data/simplearchive.tar.xz") << QStringLiteral("simplearchive") << false << false << false << false
0084                                            << false << 0 << Archive::Unencrypted << 5 << QStringLiteral("simplearchive") << QString();
0085 
0086     QTest::newRow("lzma-compressed tarball") << QFINDTESTDATA("data/simplearchive.tar.lzma") << QStringLiteral("simplearchive") << false << false << false
0087                                              << false << false << 0 << Archive::Unencrypted << 5 << QStringLiteral("simplearchive") << QString();
0088 
0089     QTest::newRow("compress (.Z) tarball") << QFINDTESTDATA("data/simplearchive.tar.Z") << QStringLiteral("simplearchive") << false << false << false << false
0090                                            << false << 0 << Archive::Unencrypted << 7 << QStringLiteral("simplearchive") << QString();
0091 
0092     QTest::newRow("lzipped tarball") << QFINDTESTDATA("data/simplearchive.tar.lz") << QStringLiteral("simplearchive") << false << false << false << false
0093                                      << false << 0 << Archive::Unencrypted << 5 << QStringLiteral("simplearchive") << QString();
0094 
0095     // Only run tests for lzop compressed files if tar.lzo format is available
0096     if (PluginManager().supportedMimeTypes().contains(QLatin1String("application/x-tzo"))) {
0097         QTest::newRow("lzop-compressed tarball") << QFINDTESTDATA("data/simplearchive.tar.lzo") << QStringLiteral("simplearchive") << false << false << false
0098                                                  << false << false << 0 << Archive::Unencrypted << 5 << QStringLiteral("simplearchive") << QString();
0099 
0100         QTest::newRow("single-file lzop compressed") << QFINDTESTDATA("data/test.png.lzo") << QStringLiteral("test.png") << true << false << true << false
0101                                                      << false << 0 << Archive::Unencrypted << 1 << QStringLiteral("test.png") << QString();
0102     } else {
0103         qDebug() << "tar.lzo format not available. Skipping lzo test.";
0104     }
0105 
0106     // Only run tests for lrzipped files if lrzip executable is found in path.
0107     if (!QStandardPaths::findExecutable(QStringLiteral("lrzip")).isEmpty()) {
0108         QTest::newRow("lrzipped tarball") << QFINDTESTDATA("data/simplearchive.tar.lrz") << QStringLiteral("simplearchive") << false << false << false << false
0109                                           << false << 0 << Archive::Unencrypted << 5 << QStringLiteral("simplearchive") << QString();
0110 
0111         QTest::newRow("single-file lrzip compressed") << QFINDTESTDATA("data/test.txt.lrz") << QStringLiteral("test.txt") << true << false << true << false
0112                                                       << false << 0 << Archive::Unencrypted << 1 << QStringLiteral("test.txt") << QString();
0113     } else {
0114         qDebug() << "lrzip executable not found in path. Skipping lrzip test.";
0115     }
0116 
0117     // Only run tests for lz4-compressed files if lz4 executable is found in path.
0118     if (!QStandardPaths::findExecutable(QStringLiteral("lz4")).isEmpty()) {
0119         QTest::newRow("lz4-compressed tarball") << QFINDTESTDATA("data/simplearchive.tar.lz4") << QStringLiteral("simplearchive") << false << false << false
0120                                                 << false << false << 0 << Archive::Unencrypted << 5 << QStringLiteral("simplearchive") << QString();
0121 
0122         QTest::newRow("single-file lz4 compressed") << QFINDTESTDATA("data/test.txt.lz4") << QStringLiteral("test.txt") << true << false << true << false
0123                                                     << false << 0 << Archive::Unencrypted << 1 << QStringLiteral("test.txt") << QString();
0124     } else {
0125         qDebug() << "lz4 executable not found in path. Skipping lz4 test.";
0126     }
0127 
0128     QTest::newRow("xar archive") << QFINDTESTDATA("data/simplearchive.xar") << QStringLiteral("simplearchive") << true << false << false << false << false << 0
0129                                  << Archive::Unencrypted << 6 << QStringLiteral("simplearchive") << QString();
0130 
0131     QTest::newRow("mimetype child of application/zip") << QFINDTESTDATA("data/test.odt") << QStringLiteral("test") << false << true << false << false << false
0132                                                        << 0 << Archive::Unencrypted << 17 << QStringLiteral("test") << QString();
0133 
0134     QTest::newRow("AppImage")
0135         << QFINDTESTDATA("data/hello-1.0-x86_64.AppImage")
0136         << QStringLiteral("hello-1.0-x86_64")
0137         // NOTE: there are 7 files in this AppImage, but libarchive reports "." as separate entry which is then skipped by the ArchiveModel.
0138         << true << false << false << false << false << 0 << Archive::Unencrypted << 7 + 1 << QStringLiteral("hello-1.0-x86_64") << QString();
0139 
0140     QTest::newRow("7z multivolume") << QFINDTESTDATA("data/archive-multivolume.7z.001") << QStringLiteral("archive-multivolume") << true << false << false
0141                                     << false << true << 3 << Archive::Unencrypted << 3 << QStringLiteral("archive-multivolume") << QString();
0142 
0143     QTest::newRow("zip with only an empty folder") << QFINDTESTDATA("data/single-empty-folder.zip") << QStringLiteral("single-empty-folder") << false << true
0144                                                    << false << true << false << 0 << Archive::Unencrypted << 1 << QStringLiteral("empty") << QString();
0145 
0146     QTest::newRow("zip created by lineageos with comment")
0147         << QFINDTESTDATA("data/addonsu-remove-14.1-x86-signed.zip") << QStringLiteral("addonsu-remove-14.1-x86-signed") << false << true << false << false
0148         << false << 0 << Archive::Unencrypted << 7 << QStringLiteral("addonsu-remove-14.1-x86-signed") << QStringLiteral("signed by SignApk");
0149 
0150     // Only run tests for zstd-compressed files if zstd executable is found in path.
0151     if (!QStandardPaths::findExecutable(QStringLiteral("zstd")).isEmpty()) {
0152         QTest::newRow("zstd-compressed tarball") << QFINDTESTDATA("data/simplearchive.tar.zst") << QStringLiteral("simplearchive") << false << false << false
0153                                                  << false << false << 0 << Archive::Unencrypted << 8 << QStringLiteral("simplearchive") << QString();
0154 
0155         QTest::newRow("single-file zstd compressed") << QFINDTESTDATA("data/test.txt.zst") << QStringLiteral("test.txt") << true << false << true << false
0156                                                      << false << 0 << Archive::Unencrypted << 1 << QStringLiteral("test.txt") << QString();
0157     } else {
0158         qDebug() << "zstd executable not found in path. Skipping zstd test.";
0159     }
0160 
0161     QTest::newRow("arj unencrypted archive with comment")
0162         << QFINDTESTDATA("data/test.arj") << QStringLiteral("test") << false << false << false << false << false << 0 << Archive::Unencrypted << 13
0163         << QStringLiteral("test") << QStringLiteral("Arj archive");
0164 
0165     QTest::newRow("arj encrypted archive") << QFINDTESTDATA("data/test_encrypted.arj") << QStringLiteral("test_encrypted") << false << false << false << false
0166                                            << false << 0 << Archive::Encrypted << 9 << QStringLiteral("test_encrypted") << QString();
0167 
0168     QTest::newRow("single-file UNIX-compressed") << QFINDTESTDATA("data/test.z") << QStringLiteral("test") << true << false << true << false << false << 0
0169                                                  << Archive::Unencrypted << 1 << QStringLiteral("test") << QString();
0170 
0171     QTest::newRow("single-file zlib compressed") << QFINDTESTDATA("data/test.zz") << QStringLiteral("test") << true << false << true << false << false << 0
0172                                                  << Archive::Unencrypted << 1 << QStringLiteral("test") << QString();
0173 
0174     QTest::newRow("single-file gz compressed") << QFINDTESTDATA("data/test.txt.gz") << QStringLiteral("test.txt") << true << false << true << false << false
0175                                                << 0 << Archive::Unencrypted << 1 << QStringLiteral("test.txt") << QString();
0176 
0177     QTest::newRow("single-file bzip compressed") << QFINDTESTDATA("data/test.txt.bz2") << QStringLiteral("test.txt") << true << false << true << false << false
0178                                                  << 0 << Archive::Unencrypted << 1 << QStringLiteral("test.txt") << QString();
0179 
0180     QTest::newRow("single-file lzma compressed") << QFINDTESTDATA("data/test.png.lzma") << QStringLiteral("test.png") << true << false << true << false << false
0181                                                  << 0 << Archive::Unencrypted << 1 << QStringLiteral("test.png") << QString();
0182 
0183     QTest::newRow("single-file compressed SVG") << QFINDTESTDATA("data/test.svgz") << QStringLiteral("test") << true << false << true << false << false << 0
0184                                                 << Archive::Unencrypted << 1 << QStringLiteral("test") << QString();
0185 
0186     QTest::newRow("stuffit unencrypted archive") << QFINDTESTDATA("data/test.sit") << QStringLiteral("test") << true << false << true << false << false << 0
0187                                                  << Archive::Unencrypted << 1 << QStringLiteral("test") << QString();
0188 }
0189 
0190 void LoadTest::testProperties()
0191 {
0192     QFETCH(QString, archivePath);
0193     auto loadJob = Archive::load(archivePath, this);
0194     QVERIFY(loadJob);
0195     loadJob->setAutoDelete(false);
0196 
0197     TestHelper::startAndWaitForResult(loadJob);
0198     auto archive = loadJob->archive();
0199 
0200     QVERIFY(archive);
0201 
0202     if (!archive->isValid()) {
0203         QVERIFY(archive->fileName().isEmpty());
0204         QVERIFY(!archive->hasComment());
0205         QVERIFY(archive->error() != NoError);
0206         QSKIP("Could not find a plugin to handle the archive. Skipping test.", SkipSingle);
0207     }
0208 
0209     QFETCH(QString, expectedBaseName);
0210     QCOMPARE(archive->completeBaseName(), expectedBaseName);
0211 
0212     QFETCH(bool, isReadOnly);
0213     QFETCH(bool, canFallbackOnReadOnly);
0214 
0215     // If the plugin supports fallback on read-only mode, we cannot be sure at this point
0216     // if the archive is going to be read-write or read-only.
0217     if (!canFallbackOnReadOnly) {
0218         QCOMPARE(archive->isReadOnly(), isReadOnly);
0219     }
0220 
0221     QFETCH(bool, isSingleFile);
0222     QCOMPARE(archive->isSingleFile(), isSingleFile);
0223 
0224     QFETCH(bool, isSingleFolder);
0225     QCOMPARE(archive->isSingleFolder(), isSingleFolder);
0226 
0227     if (isSingleFile || isSingleFolder) {
0228         QVERIFY(!archive->hasMultipleTopLevelEntries());
0229     }
0230 
0231     QFETCH(bool, isMultiVolume);
0232     QCOMPARE(archive->isMultiVolume(), isMultiVolume);
0233 
0234     QFETCH(int, numberOfVolumes);
0235     QCOMPARE(archive->numberOfVolumes(), numberOfVolumes);
0236 
0237     QFETCH(Archive::EncryptionType, expectedEncryptionType);
0238     QCOMPARE(archive->encryptionType(), expectedEncryptionType);
0239 
0240     QFETCH(QString, expectedSubfolderName);
0241     QCOMPARE(archive->subfolderName(), expectedSubfolderName);
0242 
0243     QFETCH(QString, expectedComment);
0244     QCOMPARE(archive->hasComment(), !expectedComment.isEmpty());
0245     QCOMPARE(archive->comment(), expectedComment);
0246 
0247     QFETCH(int, numberOfEntries);
0248     QCOMPARE(archive->numberOfEntries(), numberOfEntries);
0249 
0250     loadJob->deleteLater();
0251     archive->deleteLater();
0252 }
0253 
0254 #include "loadtest.moc"