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 : */