mirror of https://github.com/AxioDL/metaforce.git
469 lines
17 KiB
C++
469 lines
17 KiB
C++
/*
|
||
Copyright (C) 2005-2014 Sergey A. Tachenov
|
||
|
||
This file is part of QuaZip test suite.
|
||
|
||
QuaZip is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 2.1 of the License, or
|
||
(at your option) any later version.
|
||
|
||
QuaZip is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with QuaZip. If not, see <http://www.gnu.org/licenses/>.
|
||
|
||
See COPYING file for the full LGPL text.
|
||
|
||
Original ZIP package is copyrighted by Gilles Vollant and contributors,
|
||
see quazip/(un)zip.h files for details. Basically it's the zlib license.
|
||
*/
|
||
|
||
#include "testjlcompress.h"
|
||
|
||
#include "qztest.h"
|
||
|
||
#include <QtCore/QDir>
|
||
#include <QtCore/QFile>
|
||
#include <QtCore/QFileInfo>
|
||
#include <quazip_qt_compat.h>
|
||
|
||
#include <QtTest/QtTest>
|
||
|
||
#include <JlCompress.h>
|
||
|
||
#ifdef Q_OS_WIN
|
||
#include <windows.h>
|
||
#endif
|
||
|
||
void TestJlCompress::compressFile_data()
|
||
{
|
||
QTest::addColumn<QString>("zipName");
|
||
QTest::addColumn<QString>("fileName");
|
||
QTest::newRow("simple") << "jlsimplefile.zip" << "test0.txt";
|
||
}
|
||
|
||
void TestJlCompress::compressFile()
|
||
{
|
||
QFETCH(QString, zipName);
|
||
QFETCH(QString, fileName);
|
||
QDir curDir;
|
||
if (curDir.exists(zipName)) {
|
||
if (!curDir.remove(zipName))
|
||
QFAIL("Can't remove zip file");
|
||
}
|
||
if (!createTestFiles(QStringList() << fileName)) {
|
||
QFAIL("Can't create test file");
|
||
}
|
||
QVERIFY(JlCompress::compressFile(zipName, "tmp/" + fileName));
|
||
// get the file list and check it
|
||
QStringList fileList = JlCompress::getFileList(zipName);
|
||
QCOMPARE(fileList.count(), 1);
|
||
QVERIFY(fileList[0] == fileName);
|
||
// now test the QIODevice* overload of getFileList()
|
||
QFile zipFile(zipName);
|
||
QVERIFY(zipFile.open(QIODevice::ReadOnly));
|
||
fileList = JlCompress::getFileList(zipName);
|
||
QCOMPARE(fileList.count(), 1);
|
||
QVERIFY(fileList[0] == fileName);
|
||
zipFile.close();
|
||
removeTestFiles(QStringList() << fileName);
|
||
curDir.remove(zipName);
|
||
}
|
||
|
||
void TestJlCompress::compressFiles_data()
|
||
{
|
||
QTest::addColumn<QString>("zipName");
|
||
QTest::addColumn<QStringList>("fileNames");
|
||
QTest::newRow("simple") << "jlsimplefiles.zip" <<
|
||
(QStringList() << "test0.txt" << "test00.txt");
|
||
QTest::newRow("different subdirs") << "jlsubdirfiles.zip" <<
|
||
(QStringList() << "subdir1/test1.txt" << "subdir2/test2.txt");
|
||
}
|
||
|
||
void TestJlCompress::compressFiles()
|
||
{
|
||
QFETCH(QString, zipName);
|
||
QFETCH(QStringList, fileNames);
|
||
QDir curDir;
|
||
if (curDir.exists(zipName)) {
|
||
if (!curDir.remove(zipName))
|
||
QFAIL("Can't remove zip file");
|
||
}
|
||
if (!createTestFiles(fileNames)) {
|
||
QFAIL("Can't create test files");
|
||
}
|
||
QStringList realNamesList, shortNamesList;
|
||
foreach (QString fileName, fileNames) {
|
||
QString realName = "tmp/" + fileName;
|
||
realNamesList += realName;
|
||
shortNamesList += QFileInfo(realName).fileName();
|
||
}
|
||
QVERIFY(JlCompress::compressFiles(zipName, realNamesList));
|
||
// get the file list and check it
|
||
QStringList fileList = JlCompress::getFileList(zipName);
|
||
QCOMPARE(fileList, shortNamesList);
|
||
removeTestFiles(fileNames);
|
||
curDir.remove(zipName);
|
||
}
|
||
|
||
void TestJlCompress::compressDir_data()
|
||
{
|
||
QTest::addColumn<QString>("zipName");
|
||
QTest::addColumn<QStringList>("fileNames");
|
||
QTest::addColumn<QStringList>("expected");
|
||
QTest::newRow("simple") << "jldir.zip"
|
||
<< (QStringList() << "test0.txt" << "testdir1/test1.txt"
|
||
<< "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt")
|
||
<< (QStringList() << "test0.txt"
|
||
<< "testdir1/" << "testdir1/test1.txt"
|
||
<< "testdir2/" << "testdir2/test2.txt"
|
||
<< "testdir2/subdir/" << "testdir2/subdir/test2sub.txt");
|
||
QTest::newRow("empty dirs") << "jldir_empty.zip"
|
||
<< (QStringList() << "testdir1/" << "testdir2/testdir3/")
|
||
<< (QStringList() << "testdir1/" << "testdir2/"
|
||
<< "testdir2/testdir3/");
|
||
QTest::newRow("hidden files") << "jldir_hidden.zip"
|
||
<< (QStringList() << ".test0.txt" << "test1.txt")
|
||
<< (QStringList() << ".test0.txt" << "test1.txt");
|
||
}
|
||
|
||
void TestJlCompress::compressDir()
|
||
{
|
||
QFETCH(QString, zipName);
|
||
QFETCH(QStringList, fileNames);
|
||
QFETCH(QStringList, expected);
|
||
QDir curDir;
|
||
if (curDir.exists(zipName)) {
|
||
if (!curDir.remove(zipName))
|
||
QFAIL("Can't remove zip file");
|
||
}
|
||
if (!createTestFiles(fileNames, -1, "compressDir_tmp")) {
|
||
QFAIL("Can't create test files");
|
||
}
|
||
#ifdef Q_OS_WIN
|
||
for (int i = 0; i < fileNames.size(); ++i) {
|
||
if (fileNames.at(i).startsWith(".")) {
|
||
QString fn = "compressDir_tmp\\" + fileNames.at(i);
|
||
SetFileAttributesW(reinterpret_cast<LPCWSTR>(fn.utf16()),
|
||
FILE_ATTRIBUTE_HIDDEN);
|
||
}
|
||
}
|
||
#endif
|
||
QVERIFY(JlCompress::compressDir(zipName, "compressDir_tmp", true, QDir::Hidden));
|
||
// get the file list and check it
|
||
QStringList fileList = JlCompress::getFileList(zipName);
|
||
fileList.sort();
|
||
expected.sort();
|
||
QCOMPARE(fileList, expected);
|
||
removeTestFiles(fileNames, "compressDir_tmp");
|
||
curDir.remove(zipName);
|
||
}
|
||
|
||
void TestJlCompress::extractFile_data()
|
||
{
|
||
QTest::addColumn<QString>("zipName");
|
||
QTest::addColumn<QStringList>("fileNames");
|
||
QTest::addColumn<QString>("fileToExtract");
|
||
QTest::addColumn<QString>("destName");
|
||
QTest::addColumn<QByteArray>("encoding");
|
||
QTest::newRow("simple") << "jlextfile.zip" << (
|
||
QStringList() << "test0.txt" << "testdir1/test1.txt"
|
||
<< "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt")
|
||
<< "testdir2/test2.txt" << "test2.txt" << QByteArray();
|
||
QTest::newRow("russian") << "jlextfilerus.zip" << (
|
||
QStringList() << "test0.txt" << "testdir1/test1.txt"
|
||
<< QString::fromUtf8("testdir2/тест2.txt")
|
||
<< "testdir2/subdir/test2sub.txt")
|
||
<< QString::fromUtf8("testdir2/тест2.txt")
|
||
<< QString::fromUtf8("тест2.txt") << QByteArray("IBM866");
|
||
QTest::newRow("extract dir") << "jlextdir.zip" << (
|
||
QStringList() << "testdir1/")
|
||
<< "testdir1/" << "testdir1/" << QByteArray();
|
||
}
|
||
|
||
void TestJlCompress::extractFile()
|
||
{
|
||
QFETCH(QString, zipName);
|
||
QFETCH(QStringList, fileNames);
|
||
QFETCH(QString, fileToExtract);
|
||
QFETCH(QString, destName);
|
||
QFETCH(QByteArray, encoding);
|
||
QDir curDir;
|
||
if (!curDir.mkpath("jlext/jlfile")) {
|
||
QFAIL("Couldn't mkpath jlext/jlfile");
|
||
}
|
||
if (!createTestFiles(fileNames)) {
|
||
QFAIL("Couldn't create test files");
|
||
}
|
||
QFile srcFile("tmp/" + fileToExtract);
|
||
QFile::Permissions srcPerm = srcFile.permissions();
|
||
// Invert the "write other" flag so permissions
|
||
// are NOT default any more. Otherwise it's impossible
|
||
// to figure out whether the permissions were set correctly
|
||
// or JlCompress failed to set them completely,
|
||
// thus leaving them at the default setting.
|
||
srcPerm ^= QFile::WriteOther;
|
||
QVERIFY(srcFile.setPermissions(srcPerm));
|
||
if (!createTestArchive(zipName, fileNames,
|
||
QTextCodec::codecForName(encoding))) {
|
||
QFAIL("Can't create test archive");
|
||
}
|
||
QuaZip::setDefaultFileNameCodec(encoding);
|
||
QVERIFY(!JlCompress::extractFile(zipName, fileToExtract,
|
||
"jlext/jlfile/" + destName).isEmpty());
|
||
QFileInfo destInfo("jlext/jlfile/" + destName), srcInfo("tmp/" +
|
||
fileToExtract);
|
||
QCOMPARE(destInfo.size(), srcInfo.size());
|
||
QCOMPARE(destInfo.permissions(), srcInfo.permissions());
|
||
curDir.remove("jlext/jlfile/" + destName);
|
||
// now test the QIODevice* overload
|
||
QFile zipFile(zipName);
|
||
QVERIFY(zipFile.open(QIODevice::ReadOnly));
|
||
QVERIFY(!JlCompress::extractFile(&zipFile, fileToExtract,
|
||
"jlext/jlfile/" + destName).isEmpty());
|
||
destInfo = QFileInfo("jlext/jlfile/" + destName);
|
||
QCOMPARE(destInfo.size(), srcInfo.size());
|
||
QCOMPARE(destInfo.permissions(), srcInfo.permissions());
|
||
curDir.remove("jlext/jlfile/" + destName);
|
||
if (!fileToExtract.endsWith("/")) {
|
||
// If we aren't extracting a directory, we need to check
|
||
// that extractFile() fails if there is a directory
|
||
// with the same name as the file being extracted.
|
||
curDir.mkdir("jlext/jlfile/" + destName);
|
||
QVERIFY(JlCompress::extractFile(zipName, fileToExtract,
|
||
"jlext/jlfile/" + destName).isEmpty());
|
||
}
|
||
zipFile.close();
|
||
// Here we either delete the target dir or the dir created in the
|
||
// test above.
|
||
curDir.rmpath("jlext/jlfile/" + destName);
|
||
removeTestFiles(fileNames);
|
||
curDir.remove(zipName);
|
||
}
|
||
|
||
void TestJlCompress::extractFiles_data()
|
||
{
|
||
QTest::addColumn<QString>("zipName");
|
||
QTest::addColumn<QStringList>("fileNames");
|
||
QTest::addColumn<QStringList>("filesToExtract");
|
||
QTest::newRow("simple") << "jlextfiles.zip" << (
|
||
QStringList() << "test0.txt" << "testdir1/test1.txt"
|
||
<< "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt")
|
||
<< (QStringList() << "testdir2/test2.txt" << "testdir1/test1.txt");
|
||
}
|
||
|
||
void TestJlCompress::extractFiles()
|
||
{
|
||
QFETCH(QString, zipName);
|
||
QFETCH(QStringList, fileNames);
|
||
QFETCH(QStringList, filesToExtract);
|
||
QDir curDir;
|
||
if (!curDir.mkpath("jlext/jlfiles")) {
|
||
QFAIL("Couldn't mkpath jlext/jlfiles");
|
||
}
|
||
if (!createTestFiles(fileNames)) {
|
||
QFAIL("Couldn't create test files");
|
||
}
|
||
if (!JlCompress::compressDir(zipName, "tmp")) {
|
||
QFAIL("Couldn't create test archive");
|
||
}
|
||
QVERIFY(!JlCompress::extractFiles(zipName, filesToExtract,
|
||
"jlext/jlfiles").isEmpty());
|
||
foreach (QString fileName, filesToExtract) {
|
||
QFileInfo fileInfo("jlext/jlfiles/" + fileName);
|
||
QFileInfo extInfo("tmp/" + fileName);
|
||
QCOMPARE(fileInfo.size(), extInfo.size());
|
||
QCOMPARE(fileInfo.permissions(), extInfo.permissions());
|
||
curDir.remove("jlext/jlfiles/" + fileName);
|
||
curDir.rmpath(fileInfo.dir().path());
|
||
}
|
||
// now test the QIODevice* overload
|
||
QFile zipFile(zipName);
|
||
QVERIFY(zipFile.open(QIODevice::ReadOnly));
|
||
QVERIFY(!JlCompress::extractFiles(&zipFile, filesToExtract,
|
||
"jlext/jlfiles").isEmpty());
|
||
foreach (QString fileName, filesToExtract) {
|
||
QFileInfo fileInfo("jlext/jlfiles/" + fileName);
|
||
QFileInfo extInfo("tmp/" + fileName);
|
||
QCOMPARE(fileInfo.size(), extInfo.size());
|
||
QCOMPARE(fileInfo.permissions(), extInfo.permissions());
|
||
curDir.remove("jlext/jlfiles/" + fileName);
|
||
curDir.rmpath(fileInfo.dir().path());
|
||
}
|
||
zipFile.close();
|
||
curDir.rmpath("jlext/jlfiles");
|
||
removeTestFiles(fileNames);
|
||
curDir.remove(zipName);
|
||
}
|
||
|
||
void TestJlCompress::extractDir_data()
|
||
{
|
||
QTest::addColumn<QString>("zipName");
|
||
QTest::addColumn<QStringList>("fileNames");
|
||
QTest::addColumn<QStringList>("expectedExtracted");
|
||
QTest::addColumn<QByteArray>("fileNameCodecName");
|
||
QTest::newRow("simple") << "jlextdir.zip"
|
||
<< (QStringList() << "test0.txt" << "testdir1/test1.txt"
|
||
<< "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt")
|
||
<< (QStringList() << "test0.txt" << "testdir1/test1.txt"
|
||
<< "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt")
|
||
<< QByteArray();
|
||
QTest::newRow("separate dir") << "sepdir.zip"
|
||
<< (QStringList() << "laj/" << "laj/lajfile.txt")
|
||
<< (QStringList() << "laj/" << "laj/lajfile.txt")
|
||
<< QByteArray();
|
||
QTest::newRow("Zip Slip") << "zipslip.zip"
|
||
<< (QStringList() << "test0.txt" << "../zipslip.txt")
|
||
<< (QStringList() << "test0.txt")
|
||
<< QByteArray();
|
||
QTest::newRow("Cyrillic") << "cyrillic.zip"
|
||
<< (QStringList() << QString::fromUtf8("Ще не вмерла Україна"))
|
||
<< (QStringList() << QString::fromUtf8("Ще не вмерла Україна"))
|
||
<< QByteArray("KOI8-U");
|
||
QTest::newRow("Japaneses") << "japanese.zip"
|
||
<< (QStringList() << QString::fromUtf8("日本"))
|
||
<< (QStringList() << QString::fromUtf8("日本"))
|
||
<< QByteArray("UTF-8");
|
||
}
|
||
|
||
void TestJlCompress::extractDir()
|
||
{
|
||
QFETCH(QString, zipName);
|
||
QFETCH(QStringList, fileNames);
|
||
QFETCH(QStringList, expectedExtracted);
|
||
QFETCH(QByteArray, fileNameCodecName);
|
||
QTextCodec *fileNameCodec = NULL;
|
||
if (!fileNameCodecName.isEmpty())
|
||
fileNameCodec = QTextCodec::codecForName(fileNameCodecName);
|
||
QDir curDir;
|
||
if (!curDir.mkpath("jlext/jldir")) {
|
||
QFAIL("Couldn't mkpath jlext/jldir");
|
||
}
|
||
if (!createTestFiles(fileNames)) {
|
||
QFAIL("Couldn't create test files");
|
||
}
|
||
if (!createTestArchive(zipName, fileNames, fileNameCodec)) {
|
||
QFAIL("Couldn't create test archive");
|
||
}
|
||
QStringList extracted;
|
||
if (fileNameCodec == NULL)
|
||
extracted = JlCompress::extractDir(zipName, "jlext/jldir");
|
||
else // test both overloads here
|
||
extracted = JlCompress::extractDir(zipName, fileNameCodec, "jlext/jldir");
|
||
QCOMPARE(extracted.count(), expectedExtracted.count());
|
||
const QString dir = "jlext/jldir/";
|
||
foreach (QString fileName, expectedExtracted) {
|
||
QString fullName = dir + fileName;
|
||
QFileInfo fileInfo(fullName);
|
||
QFileInfo extInfo("tmp/" + fileName);
|
||
if (!fileInfo.isDir())
|
||
QCOMPARE(fileInfo.size(), extInfo.size());
|
||
QCOMPARE(fileInfo.permissions(), extInfo.permissions());
|
||
curDir.remove(fullName);
|
||
curDir.rmpath(fileInfo.dir().path());
|
||
QString absolutePath = QDir(dir).absoluteFilePath(fileName);
|
||
if (fileInfo.isDir() && !absolutePath.endsWith('/'))
|
||
absolutePath += '/';
|
||
QVERIFY(extracted.contains(absolutePath));
|
||
}
|
||
// now test the QIODevice* overload
|
||
QFile zipFile(zipName);
|
||
QVERIFY(zipFile.open(QIODevice::ReadOnly));
|
||
if (fileNameCodec == NULL)
|
||
extracted = JlCompress::extractDir(&zipFile, "jlext/jldir");
|
||
else // test both overloads here
|
||
extracted = JlCompress::extractDir(&zipFile, fileNameCodec, "jlext/jldir");
|
||
QCOMPARE(extracted.count(), expectedExtracted.count());
|
||
foreach (QString fileName, expectedExtracted) {
|
||
QString fullName = dir + fileName;
|
||
QFileInfo fileInfo(fullName);
|
||
QFileInfo extInfo("tmp/" + fileName);
|
||
if (!fileInfo.isDir())
|
||
QCOMPARE(fileInfo.size(), extInfo.size());
|
||
QCOMPARE(fileInfo.permissions(), extInfo.permissions());
|
||
curDir.remove(fullName);
|
||
curDir.rmpath(fileInfo.dir().path());
|
||
QString absolutePath = QDir(dir).absoluteFilePath(fileName);
|
||
if (fileInfo.isDir() && !absolutePath.endsWith('/'))
|
||
absolutePath += '/';
|
||
QVERIFY(extracted.contains(absolutePath));
|
||
}
|
||
zipFile.close();
|
||
curDir.rmpath("jlext/jldir");
|
||
removeTestFiles(fileNames);
|
||
curDir.remove(zipName);
|
||
}
|
||
|
||
void TestJlCompress::zeroPermissions()
|
||
{
|
||
QuaZip zipCreator("zero.zip");
|
||
QVERIFY(zipCreator.open(QuaZip::mdCreate));
|
||
QuaZipFile zeroFile(&zipCreator);
|
||
QuaZipNewInfo newInfo("zero.txt");
|
||
newInfo.externalAttr = 0; // should be zero anyway, but just in case
|
||
QVERIFY(zeroFile.open(QIODevice::WriteOnly, newInfo));
|
||
zeroFile.close();
|
||
zipCreator.close();
|
||
QVERIFY(!JlCompress::extractFile("zero.zip", "zero.txt").isEmpty());
|
||
QVERIFY(QFile("zero.txt").permissions() != 0);
|
||
QDir curDir;
|
||
curDir.remove("zero.zip");
|
||
curDir.remove("zero.txt");
|
||
}
|
||
|
||
#ifdef QUAZIP_SYMLINK_TEST
|
||
|
||
void TestJlCompress::symlinkHandling()
|
||
{
|
||
QStringList fileNames { "file.txt" };
|
||
if (!createTestFiles(fileNames)) {
|
||
QFAIL("Couldn't create test files");
|
||
}
|
||
QVERIFY(QFile::link("file.txt", "tmp/link.txt"));
|
||
fileNames << "link.txt";
|
||
QVERIFY(JlCompress::compressDir("symlink.zip", "tmp"));
|
||
QDir curDir;
|
||
QVERIFY(curDir.mkpath("extsymlink"));
|
||
QVERIFY(!JlCompress::extractDir("symlink.zip", "extsymlink").isEmpty());
|
||
QFileInfo linkInfo("extsymlink/link.txt");
|
||
QVERIFY(quazip_is_symlink(linkInfo));
|
||
removeTestFiles(fileNames, "extsymlink");
|
||
removeTestFiles(fileNames, "tmp");
|
||
curDir.remove("symlink.zip");
|
||
}
|
||
|
||
#endif
|
||
|
||
#ifdef QUAZIP_SYMLINK_EXTRACTION_ON_WINDOWS_TEST
|
||
|
||
void TestJlCompress::symlinkExtractionOnWindows()
|
||
{
|
||
QuaZip zipWithSymlinks("withSymlinks.zip");
|
||
QVERIFY(zipWithSymlinks.open(QuaZip::mdCreate));
|
||
QuaZipFile file(&zipWithSymlinks);
|
||
QVERIFY(file.open(QIODevice::WriteOnly, QuaZipNewInfo("file.txt")));
|
||
file.write("contents");
|
||
file.close();
|
||
QuaZipNewInfo symlinkInfo("symlink.txt");
|
||
symlinkInfo.externalAttr |= 0120000 << 16; // symlink attr
|
||
QuaZipFile symlink(&zipWithSymlinks);
|
||
QVERIFY(symlink.open(QIODevice::WriteOnly, symlinkInfo));
|
||
symlink.write("file.txt"); // link target goes into contents
|
||
symlink.close();
|
||
zipWithSymlinks.close();
|
||
QCOMPARE(zipWithSymlinks.getZipError(), ZIP_OK);
|
||
// The best we can do here is to test that extraction works at all,
|
||
// because it's hard to say what should be the “correct” result when
|
||
// trying to extract symbolic links on Windows.
|
||
QVERIFY(!JlCompress::extractDir("withSymlinks.zip", "symlinksOnWindows").isEmpty());
|
||
QDir curDir;
|
||
curDir.remove("withSymlinks.zip");
|
||
removeTestFiles(QStringList() << "file.txt" << "symlink.txt", "symlinksOnWindows");
|
||
}
|
||
|
||
#endif
|