Warning, file /utilities/basket/src/tests/archivetest.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /**
0002  * SPDX-FileCopyrightText: (C) 2021 Sebastian Engel <dev@sebastianengel.eu>
0003  * SPDX-License-Identifier: GPL-2.0-or-later
0004  */
0005 
0006 #include <KTar>
0007 
0008 #include <QObject>
0009 #include <QtTest/QtTest>
0010 
0011 #include <algorithm>
0012 #include <archive.h>
0013 #include <memory>
0014 
0015 class ArchiveTest : public QObject
0016 {
0017     Q_OBJECT
0018 private Q_SLOTS:
0019     void initTestCase();
0020 
0021     void testExtractArchive();
0022     void testCreateArchive();
0023 
0024     void cleanupTestCase();
0025 
0026 private:
0027     bool compareDirTree(const QString &toTestPath, const QString &referencePath);
0028     bool compareDirHashes(const QString &toTestPath, const QString &referencePath);
0029     QStringList createDirTree(const QString &path, bool returnRelativePaths);
0030     //    QByteArray fileHash(const QString &path, QCryptographicHash::Algorithm hashAlgorithm);
0031 };
0032 
0033 QTEST_MAIN(ArchiveTest)
0034 
0035 void ArchiveTest::testExtractArchive()
0036 {
0037     const QString referencePath = QFINDTESTDATA("archive/");
0038 
0039     // Test the Archive::extractArchive function
0040     QString referenceSource = QDir::currentPath() + QDir::separator() + "sample_source";
0041     QString testArchive = referencePath + "sample.baskets";
0042     QString testPath = QDir::currentPath() + QDir::separator() + "sample/";
0043     Archive::IOErrorCode ioCode = Archive::extractArchive(testArchive, testPath, false);
0044 
0045     QVERIFY2(ioCode == Archive::IOErrorCode::NoError, "An issue occured while extracting .baskets archive");
0046     QVERIFY2(compareDirTree(testPath, referenceSource), "Extracted .baskets archive is not identical with the reference source");
0047     QVERIFY2(compareDirHashes(testPath, referenceSource), "Extracted .baskets archive content is not identical with the reference source (hashes different)");
0048 
0049     QDir dir(testPath);
0050     dir.removeRecursively();
0051 
0052     // Test the Archive::extractArchive function with incompatible file
0053     testArchive = referencePath + "notABasket.baskets";
0054     testPath = QStringLiteral("notABasket/");
0055     ioCode = Archive::extractArchive(testArchive, testPath, false);
0056 
0057     QVERIFY2(ioCode == Archive::IOErrorCode::NotABasketArchive, ".baskets was not recoqnized as incompatible baskets file");
0058 
0059     // Test the Archive::extractArchive function with incompatible version
0060     testArchive = referencePath + "incompatible.baskets";
0061     testPath = QStringLiteral("incompatible/");
0062     ioCode = Archive::extractArchive(testArchive, testPath, false);
0063 
0064     QVERIFY2(ioCode == Archive::IOErrorCode::IncompatibleBasketVersion, ".baskets was not recoqnized as incompatible baskets file");
0065 
0066     /// \todo prepare more tests
0067     // Test the Archive::extractArchive function with corrupt file
0068     // Test the Archive::extractArchive function with 0-length preview
0069     // Test the Archive::extractArchive function with 0-length tar archive
0070     // Test the Archive::extractArchive function with non integer values as size
0071 }
0072 
0073 void ArchiveTest::testCreateArchive()
0074 {
0075     const QString referencePath = QFINDTESTDATA("archive/");
0076 
0077     // Test the Archive::createArchiveFromSource function
0078 
0079     QString referenceSource = referencePath + "sample.baskets";
0080     QString testArchive = "test.baskets";
0081 
0082     QFile(testArchive).remove();
0083 
0084     QString testSourcePath = QDir::currentPath() + QDir::separator() + "sample_source/";
0085     Archive::IOErrorCode ioCode = Archive::createArchiveFromSource(testSourcePath, testSourcePath + "preview.png", testArchive);
0086 
0087     QVERIFY2(ioCode == Archive::IOErrorCode::NoError, "An issue occured while creating a .baskets archive");
0088 
0089     /// \todo find a simple way to compare created archive. KTar could write specific meta data...
0090 
0091     //    auto hashRef = fileHash(referenceSource, QCryptographicHash::Sha256);
0092     //    auto hashTest = fileHash(testArchive, QCryptographicHash::Sha256);
0093 
0094     QFile testArchiveFile(testArchive);
0095     testArchiveFile.remove();
0096 
0097     //    QVERIFY2(hashRef == hashTest, "Created .baskets archive is not identical with the reference (hashes different)");
0098 }
0099 
0100 void ArchiveTest::initTestCase()
0101 {
0102     const QString referenceData = QFINDTESTDATA("archive/sample_source.tar.gz");
0103 
0104     KTar archive(referenceData, "application/x-gzip");
0105 
0106     // Open the archive
0107     archive.open(QIODevice::ReadOnly);
0108     QString destination = QDir::currentPath();
0109     archive.directory()->copyTo(destination, true);
0110     archive.close();
0111 }
0112 
0113 void ArchiveTest::cleanupTestCase()
0114 {
0115     QStringList toDeleteDirectories{"sample_source", "sample", "notABasket", "incompatible"};
0116 
0117     std::for_each(toDeleteDirectories.begin(), toDeleteDirectories.end(), [](const QString &path) {
0118         QDir dir(path);
0119         dir.removeRecursively();
0120     });
0121 
0122     QStringList toDeleteFiles{"test.baskets"};
0123 
0124     std::for_each(toDeleteDirectories.begin(), toDeleteDirectories.end(), [](const QString &path) {
0125         QFile file(path);
0126         file.remove();
0127     });
0128 }
0129 
0130 bool ArchiveTest::compareDirTree(const QString &toTestPath, const QString &referencePath)
0131 {
0132     const auto testPathDirTree = createDirTree(toTestPath, true);
0133     const auto referencePathDirTree = createDirTree(referencePath, true);
0134 
0135     if (testPathDirTree.size() != referencePathDirTree.size()) {
0136         return false;
0137     }
0138 
0139     // until C++14, this test is required for using std::mismatch
0140     if (testPathDirTree.size() > referencePathDirTree.size()) {
0141         return false;
0142     }
0143 
0144     auto mismatched = std::mismatch(testPathDirTree.begin(), testPathDirTree.end(), referencePathDirTree.begin());
0145 
0146     return !(mismatched.first != testPathDirTree.end() || mismatched.second != referencePathDirTree.end());
0147 }
0148 
0149 QStringList ArchiveTest::createDirTree(const QString &path, const bool returnRelativePaths)
0150 {
0151     QStringList dirTree;
0152     QDir dir(path);
0153 
0154     QDirIterator it(dir.absolutePath(), QDir::Files, QDirIterator::Subdirectories);
0155 
0156     if (returnRelativePaths) {
0157         while (it.hasNext()) {
0158             dirTree.append(dir.relativeFilePath(it.next()));
0159         }
0160     } else {
0161         while (it.hasNext()) {
0162             dirTree.append(it.next());
0163         }
0164     }
0165 
0166     dirTree.sort();
0167 
0168     return dirTree;
0169 }
0170 
0171 bool ArchiveTest::compareDirHashes(const QString &toTestPath, const QString &referencePath)
0172 {
0173     const auto testPathDirTree = createDirTree(toTestPath, false);
0174     const auto referencePathDirTree = createDirTree(referencePath, false);
0175 
0176     if (testPathDirTree.size() != referencePathDirTree.size()) {
0177         return false;
0178     }
0179 
0180     // until C++14, this test is required for using std::mismatch
0181     if (testPathDirTree.size() > referencePathDirTree.size()) {
0182         return false;
0183     }
0184 
0185     QCryptographicHash hashTest(QCryptographicHash::Sha256);
0186     QCryptographicHash hashReference(QCryptographicHash::Sha256);
0187 
0188     std::for_each(testPathDirTree.begin(), testPathDirTree.end(), [&](const QString &path) {
0189         QFile file(path);
0190         if (!file.open(QIODevice::ReadOnly)) {
0191             hashTest.addData(&file);
0192             file.close();
0193         }
0194     });
0195 
0196     std::for_each(referencePathDirTree.begin(), referencePathDirTree.end(), [&](const QString &path) {
0197         QFile file(path);
0198         if (!file.open(QIODevice::ReadOnly)) {
0199             hashTest.addData(&file);
0200             file.close();
0201         }
0202     });
0203 
0204     return hashTest.result() == hashReference.result();
0205 }
0206 
0207 // QByteArray ArchiveTest::fileHash(const QString &path, QCryptographicHash::Algorithm hashAlgorithm)
0208 //{
0209 //    QFile file(path);
0210 //    if (file.open(QFile::ReadOnly)) {
0211 //        QCryptographicHash hash(hashAlgorithm);
0212 //        if (hash.addData(&file)) {
0213 //            return hash.result();
0214 //        }
0215 //    }
0216 //    return QByteArray();
0217 //}
0218 
0219 #include "archivetest.moc"
0220 /* vim: set et sts=4 sw=4 ts=8 tw=0 : */