source: s10k/CommonLibs/quazip-0.7.2/qztest/testquazipfile.cpp @ 1096

Last change on this file since 1096 was 1096, checked in by s10k, 19 months ago

Added zlib, quazip, basicxmlsyntaxhighlighter, conditionalsemaphore and linenumberdisplay libraries. zlib and quazip are pre-compiled, but you can compile them yourself, just delete the dll files (or equivalent binary files to your OS)

File size: 20.5 KB
Line 
1/*
2Copyright (C) 2005-2014 Sergey A. Tachenov
3
4This file is part of QuaZIP test suite.
5
6QuaZIP is free software: you can redistribute it and/or modify
7it under the terms of the GNU Lesser General Public License as published by
8the Free Software Foundation, either version 2.1 of the License, or
9(at your option) any later version.
10
11QuaZIP is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU Lesser General Public License for more details.
15
16You should have received a copy of the GNU Lesser General Public License
17along with QuaZIP.  If not, see <http://www.gnu.org/licenses/>.
18
19See COPYING file for the full LGPL text.
20
21Original ZIP package is copyrighted by Gilles Vollant and contributors,
22see quazip/(un)zip.h files for details. Basically it's the zlib license.
23*/
24
25#include "testquazipfile.h"
26
27#include "qztest.h"
28
29#include <quazip/JlCompress.h>
30#include <quazip/quazipfile.h>
31#include <quazip/quazip.h>
32
33#include <QFile>
34#include <QString>
35#include <QStringList>
36
37#include <QtTest/QtTest>
38
39void TestQuaZipFile::zipUnzip_data()
40{
41    QTest::addColumn<QString>("zipName");
42    QTest::addColumn<QStringList>("fileNames");
43    QTest::addColumn<QByteArray>("fileNameCodec");
44    QTest::addColumn<QByteArray>("password");
45    QTest::addColumn<bool>("zip64");
46    QTest::newRow("simple") << "simple.zip" << (
47            QStringList() << "test0.txt" << "testdir1/test1.txt"
48            << "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt")
49        << QByteArray() << QByteArray() << false;
50    QTest::newRow("Cyrillic") << "cyrillic.zip" << (
51            QStringList()
52            << QString::fromUtf8("русское имя файла с пробелами.txt"))
53        << QByteArray("IBM866") << QByteArray() << false;
54    QTest::newRow("password") << "password.zip" << (
55            QStringList() << "test.txt")
56        << QByteArray() << QByteArray("PassPass") << false;
57    QTest::newRow("zip64") << "zip64.zip" << (
58            QStringList() << "test64.txt")
59        << QByteArray() << QByteArray() << true;
60}
61
62void TestQuaZipFile::zipUnzip()
63{
64    QFETCH(QString, zipName);
65    QFETCH(QStringList, fileNames);
66    QFETCH(QByteArray, fileNameCodec);
67    QFETCH(QByteArray, password);
68    QFETCH(bool, zip64);
69    QFile testFile(zipName);
70    if (testFile.exists()) {
71        if (!testFile.remove()) {
72            QFAIL("Couldn't remove existing archive to create a new one");
73        }
74    }
75    if (!createTestFiles(fileNames)) {
76        QFAIL("Couldn't create test files for zipping");
77    }
78    QuaZip testZip(&testFile);
79    testZip.setZip64Enabled(zip64);
80    if (!fileNameCodec.isEmpty())
81        testZip.setFileNameCodec(fileNameCodec);
82    QVERIFY(testZip.open(QuaZip::mdCreate));
83    QString comment = "Test comment";
84    testZip.setComment(comment);
85    foreach (QString fileName, fileNames) {
86        QFile inFile("tmp/" + fileName);
87        if (!inFile.open(QIODevice::ReadOnly)) {
88            qDebug("File name: %s", fileName.toUtf8().constData());
89            QFAIL("Couldn't open input file");
90        }
91        QuaZipFile outFile(&testZip);
92        QVERIFY(outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileName,
93                        inFile.fileName()),
94                password.isEmpty() ? NULL : password.constData()));
95        for (qint64 pos = 0, len = inFile.size(); pos < len; ) {
96            char buf[4096];
97            qint64 readSize = qMin(static_cast<qint64>(4096), len - pos);
98            qint64 l;
99            if ((l = inFile.read(buf, readSize)) != readSize) {
100                qDebug("Reading %ld bytes from %s at %ld returned %ld",
101                        static_cast<long>(readSize),
102                        fileName.toUtf8().constData(),
103                        static_cast<long>(pos),
104                        static_cast<long>(l));
105                QFAIL("Read failure");
106            }
107            QVERIFY(outFile.write(buf, readSize));
108            pos += readSize;
109        }
110        inFile.close();
111        outFile.close();
112        QCOMPARE(outFile.getZipError(), ZIP_OK);
113    }
114    testZip.close();
115    QCOMPARE(testZip.getZipError(), ZIP_OK);
116    // now test unzip
117    QuaZip testUnzip(&testFile);
118    if (!fileNameCodec.isEmpty())
119        testUnzip.setFileNameCodec(fileNameCodec);
120    QVERIFY(testUnzip.open(QuaZip::mdUnzip));
121    QCOMPARE(testUnzip.getComment(), comment);
122    QVERIFY(testUnzip.goToFirstFile());
123    foreach (QString fileName, fileNames) {
124        QuaZipFileInfo64 info;
125        QVERIFY(testUnzip.getCurrentFileInfo(&info));
126        QCOMPARE(info.name, fileName);
127        QCOMPARE(info.isEncrypted(), !password.isEmpty());
128        QFile original("tmp/" + fileName);
129        QVERIFY(original.open(QIODevice::ReadOnly));
130        QuaZipFile archived(&testUnzip);
131        QVERIFY(archived.open(QIODevice::ReadOnly,
132                         password.isEmpty() ? NULL : password.constData()));
133        QByteArray originalData = original.readAll();
134        QByteArray archivedData = archived.readAll();
135        QCOMPARE(archivedData, originalData);
136        testUnzip.goToNextFile();
137    }
138    if (!password.isEmpty()) {
139        QVERIFY(testUnzip.goToFirstFile());
140        QuaZipFileInfo64 info;
141        QVERIFY(testUnzip.getCurrentFileInfo(&info));
142        QFile original("tmp/" + info.name);
143        QVERIFY(original.open(QIODevice::ReadOnly));
144        QuaZipFile archived(&testUnzip);
145        QVERIFY(archived.open(QIODevice::ReadOnly, "WrongPassword"));
146        QByteArray originalData = original.readAll();
147        QByteArray archivedData = archived.readAll();
148        QVERIFY(archivedData != originalData);
149    }
150    testUnzip.close();
151    QCOMPARE(testUnzip.getZipError(), UNZ_OK);
152    // clean up
153    removeTestFiles(fileNames);
154    testFile.remove();
155}
156
157void TestQuaZipFile::bytesAvailable_data()
158{
159    QTest::addColumn<QString>("zipName");
160    QTest::addColumn<QStringList>("fileNames");
161    QTest::newRow("simple") << "test.zip" << (
162            QStringList() << "test0.txt" << "testdir1/test1.txt"
163            << "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt");
164}
165
166void TestQuaZipFile::bytesAvailable()
167{
168    QFETCH(QString, zipName);
169    QFETCH(QStringList, fileNames);
170    QDir curDir;
171    if (!createTestFiles(fileNames)) {
172        QFAIL("Couldn't create test files");
173    }
174    if (!JlCompress::compressDir(zipName, "tmp")) {
175        QFAIL("Couldn't create test archive");
176    }
177    QuaZip testZip(zipName);
178    QVERIFY(testZip.open(QuaZip::mdUnzip));
179    foreach (QString fileName, fileNames) {
180        QFileInfo fileInfo("tmp/" + fileName);
181        QVERIFY(testZip.setCurrentFile(fileName));
182        QuaZipFile zipFile(&testZip);
183        QVERIFY(zipFile.open(QIODevice::ReadOnly));
184        QCOMPARE(zipFile.bytesAvailable(), fileInfo.size());
185        QCOMPARE(zipFile.read(1).size(), 1);
186        QCOMPARE(zipFile.bytesAvailable(), fileInfo.size() - 1);
187        QCOMPARE(zipFile.read(fileInfo.size() - 1).size(),
188                static_cast<int>(fileInfo.size() - 1));
189        QCOMPARE(zipFile.bytesAvailable(), (qint64) 0);
190    }
191    removeTestFiles(fileNames);
192    testZip.close();
193    curDir.remove(zipName);
194}
195
196void TestQuaZipFile::atEnd_data()
197{
198    bytesAvailable_data();
199}
200
201void TestQuaZipFile::atEnd()
202{
203    QFETCH(QString, zipName);
204    QFETCH(QStringList, fileNames);
205    QDir curDir;
206    if (!createTestFiles(fileNames)) {
207        QFAIL("Couldn't create test files");
208    }
209    if (!JlCompress::compressDir(zipName, "tmp")) {
210        QFAIL("Couldn't create test archive");
211    }
212    QuaZip testZip(zipName);
213    QVERIFY(testZip.open(QuaZip::mdUnzip));
214    foreach (QString fileName, fileNames) {
215        QFileInfo fileInfo("tmp/" + fileName);
216        QVERIFY(testZip.setCurrentFile(fileName));
217        QuaZipFile zipFile(&testZip);
218        QVERIFY(zipFile.open(QIODevice::ReadOnly));
219        QCOMPARE(zipFile.atEnd(), false);
220        QCOMPARE(zipFile.read(1).size(), 1);
221        QCOMPARE(zipFile.atEnd(), false);
222        QCOMPARE(zipFile.read(fileInfo.size() - 1).size(),
223                static_cast<int>(fileInfo.size() - 1));
224        QCOMPARE(zipFile.atEnd(), true);
225    }
226    removeTestFiles(fileNames);
227    testZip.close();
228    curDir.remove(zipName);
229}
230
231void TestQuaZipFile::pos_data()
232{
233    bytesAvailable_data();
234}
235
236void TestQuaZipFile::pos()
237{
238    QFETCH(QString, zipName);
239    QFETCH(QStringList, fileNames);
240    QDir curDir;
241    if (!createTestFiles(fileNames)) {
242        QFAIL("Couldn't create test files");
243    }
244    if (!JlCompress::compressDir(zipName, "tmp")) {
245        QFAIL("Couldn't create test archive");
246    }
247    QuaZip testZip(zipName);
248    QVERIFY(testZip.open(QuaZip::mdUnzip));
249    foreach (QString fileName, fileNames) {
250        QFileInfo fileInfo("tmp/" + fileName);
251        QVERIFY(testZip.setCurrentFile(fileName));
252        QuaZipFile zipFile(&testZip);
253        QVERIFY(zipFile.open(QIODevice::ReadOnly));
254        QCOMPARE(zipFile.pos(), (qint64) 0);
255        QCOMPARE(zipFile.read(1).size(), 1);
256        QCOMPARE(zipFile.pos(), (qint64) 1);
257        QCOMPARE(zipFile.read(fileInfo.size() - 1).size(),
258                static_cast<int>(fileInfo.size() - 1));
259        QCOMPARE(zipFile.pos(), fileInfo.size());
260    }
261    removeTestFiles(fileNames);
262    testZip.close();
263    curDir.remove(zipName);
264}
265
266void TestQuaZipFile::getZip()
267{
268    QuaZip testZip;
269    QuaZipFile f1(&testZip);
270    QCOMPARE(f1.getZip(), &testZip);
271    QuaZipFile f2("doesntexist.zip", "someFile");
272    QCOMPARE(f2.getZip(), static_cast<QuaZip*>(NULL));
273    f2.setZip(&testZip);
274    QCOMPARE(f2.getZip(), &testZip);
275}
276
277void TestQuaZipFile::setZipName()
278{
279    QString testFileName = "testZipName.txt";
280    QString testZipName = "testZipName.zip";
281    QVERIFY(createTestFiles(QStringList() << testFileName));
282    QVERIFY(createTestArchive(testZipName, QStringList() << testFileName));
283    QuaZipFile testFile;
284    testFile.setZipName(testZipName);
285    QCOMPARE(testFile.getZipName(), testZipName);
286    testFile.setFileName(testFileName);
287    QVERIFY(testFile.open(QIODevice::ReadOnly));
288    testFile.close();
289    removeTestFiles(QStringList() << testFileName);
290    QDir curDir;
291    curDir.remove(testZipName);
292}
293
294void TestQuaZipFile::getFileInfo()
295{
296    QuaZipFileInfo info32;
297    QuaZipFileInfo64 info64;
298    QString testFileName = "testZipName.txt";
299    QStringList testFiles;
300    testFiles << testFileName;
301    QString testZipName = "testZipName.zip";
302    QVERIFY(createTestFiles(testFiles));
303    QVERIFY(createTestArchive(testZipName, testFiles));
304    QuaZipFile testFile;
305    testFile.setZipName(testZipName);
306    testFile.setFileName(testFileName);
307    QVERIFY(testFile.open(QIODevice::ReadOnly));
308    QVERIFY(testFile.getFileInfo(&info32));
309    QVERIFY(testFile.getFileInfo(&info64));
310    QCOMPARE(info32.name, info64.name);
311    QCOMPARE(info32.versionCreated, info64.versionCreated);
312    QCOMPARE(info32.versionNeeded, info64.versionNeeded);
313    QCOMPARE(info32.flags, info64.flags);
314    QCOMPARE(info32.method, info64.method);
315    QCOMPARE(info32.dateTime, info64.dateTime);
316    QCOMPARE(info32.crc, info64.crc);
317    QCOMPARE(info32.compressedSize,
318             static_cast<quint32>(info64.compressedSize));
319    QCOMPARE(info32.uncompressedSize,
320             static_cast<quint32>(info64.uncompressedSize));
321    QCOMPARE(info32.diskNumberStart, info64.diskNumberStart);
322    QCOMPARE(info32.internalAttr, info64.internalAttr);
323    QCOMPARE(info32.externalAttr, info64.externalAttr);
324    QCOMPARE(info32.comment, info64.comment);
325    QCOMPARE(info32.extra, info64.extra);
326    testFile.close();
327    removeTestFiles(testFiles);
328    QDir curDir;
329    curDir.remove(testZipName);
330}
331
332void TestQuaZipFile::setFileName()
333{
334    QString testFileName = "testZipName.txt";
335    QString testZipName = "testZipName.zip";
336    QVERIFY(createTestFiles(QStringList() << testFileName));
337    QVERIFY(createTestArchive(testZipName, QStringList() << testFileName));
338    QuaZipFile testFile(testZipName);
339    testFile.setFileName(testFileName.toUpper());
340#ifdef Q_OS_WIN
341    QVERIFY(testFile.open(QIODevice::ReadOnly));
342    testFile.close();
343#else
344    QVERIFY(!testFile.open(QIODevice::ReadOnly));
345#endif
346    testFile.setFileName(testFileName.toUpper(), QuaZip::csInsensitive);
347    QCOMPARE(testFile.getCaseSensitivity(), QuaZip::csInsensitive);
348    QVERIFY(testFile.open(QIODevice::ReadOnly));
349    QCOMPARE(testFile.getActualFileName(), testFileName);
350    testFile.close();
351    testFile.setFileName(testFileName.toUpper(), QuaZip::csSensitive);
352    QCOMPARE(testFile.getFileName(), testFileName.toUpper());
353    QCOMPARE(testFile.getActualFileName(), QString());
354    QVERIFY(!testFile.open(QIODevice::ReadOnly));
355    testFile.setFileName(testFileName);
356    removeTestFiles(QStringList() << testFileName);
357    QDir curDir;
358    curDir.remove(testZipName);
359}
360
361void TestQuaZipFile::constructorDestructor()
362{
363    // Just test that all constructors and destructors are available.
364    // (So there are none that are declared but not defined.)
365    QuaZip testZip;
366    QuaZipFile *f1 = new QuaZipFile();
367    delete f1; // test D0 destructor
368    QObject parent;
369    QuaZipFile f2(&testZip, &parent);
370    QuaZipFile f3(&parent);
371    QuaZipFile f4("zipName.zip");
372    QuaZipFile f5("zipName.zip", "fileName.txt", QuaZip::csDefault, &parent);
373}
374
375void TestQuaZipFile::setFileAttrs()
376{
377    QuaZip testZip("setFileAttrs.zip");
378    QVERIFY(testZip.open(QuaZip::mdCreate));
379    QuaZipFile zipFile(&testZip);
380    QuaZipNewInfo newInfo("testPerm.txt");
381    newInfo.setPermissions(QFile::ReadOwner);
382    QVERIFY(zipFile.open(QIODevice::WriteOnly, newInfo));
383    zipFile.close();
384    QString fileTestAttr = "testAttr.txt";
385    QStringList fileNames;
386    fileNames << fileTestAttr;
387    QVERIFY(createTestFiles(fileNames));
388    newInfo.name = fileTestAttr;
389    newInfo.setFileDateTime("tmp/" + fileTestAttr);
390    newInfo.setFilePermissions("tmp/" + fileTestAttr);
391    QVERIFY(zipFile.open(QIODevice::WriteOnly, newInfo));
392    zipFile.close();
393    testZip.close();
394    QuaZipFileInfo64 info;
395    {
396        QuaZipFile readFilePerm("setFileAttrs.zip", "testPerm.txt");
397        QVERIFY(readFilePerm.open(QIODevice::ReadOnly));
398        QVERIFY(readFilePerm.getFileInfo(&info));
399        QCOMPARE(info.getPermissions(), QFile::ReadOwner);
400        readFilePerm.close();
401    }
402    {
403        QuaZipFile readFileAttrs("setFileAttrs.zip", "testAttr.txt");
404        QVERIFY(readFileAttrs.open(QIODevice::ReadOnly));
405        QVERIFY(readFileAttrs.getFileInfo(&info));
406        QFileInfo srcInfo("tmp/" + fileTestAttr);
407        QFile::Permissions usedPermissions =
408                QFile::WriteOwner | QFile::ReadOwner | QFile::ExeOwner |
409                QFile::WriteGroup | QFile::ReadGroup | QFile::ExeGroup |
410                QFile::WriteOther | QFile::ReadOther | QFile::ExeOther;
411        QCOMPARE(info.getPermissions() & usedPermissions,
412                 srcInfo.permissions() & usedPermissions);
413        // I really hope Qt 6 will use quint64 for time_t!
414        quint64 newTime = info.dateTime.toTime_t();
415        quint64 oldTime = srcInfo.lastModified().toTime_t();
416        // ZIP uses weird format with 2 second precision
417        QCOMPARE(newTime / 2, oldTime / 2);
418        readFileAttrs.close();
419    }
420    removeTestFiles(fileNames);
421    QDir().remove(testZip.getZipName());
422}
423
424void TestQuaZipFile::largeFile()
425{
426    QDir curDir;
427    QVERIFY(curDir.mkpath("tmp"));
428    QFile fakeLargeFile("tmp/large.zip");
429    QVERIFY(fakeLargeFile.open(QIODevice::WriteOnly));
430    QDataStream ds(&fakeLargeFile);
431    ds.setByteOrder(QDataStream::LittleEndian);
432    QList<qint64> localOffsets;
433    const int numFiles = 2; // name fixed to 5 bytes, so MAX 10 FILES!!!
434    for (int i = 0; i < numFiles; ++i) {
435        localOffsets.append(fakeLargeFile.pos());
436        QBuffer extra;
437        extra.open(QIODevice::WriteOnly);
438        QDataStream es(&extra);
439        es.setByteOrder(QDataStream::LittleEndian);
440        // prepare extra
441        es << static_cast<quint16>(0x0001u); // zip64
442        es << static_cast<quint16>(16); // extra data size
443        es << static_cast<quint64>(0); // uncompressed size
444        es << static_cast<quint64>(0); // compressed size
445        // now the local header
446        ds << static_cast<quint32>(0x04034b50u); // local magic
447        ds << static_cast<quint16>(45); // version needed
448        ds << static_cast<quint16>(0); // flags
449        ds << static_cast<quint16>(0); // method
450        ds << static_cast<quint16>(0); // time 00:00:00
451        ds << static_cast<quint16>(0x21); // date 1980-01-01
452        ds << static_cast<quint32>(0); // CRC-32
453        ds << static_cast<quint32>(0xFFFFFFFFu); // compressed size
454        ds << static_cast<quint32>(0xFFFFFFFFu); // uncompressed size
455        ds << static_cast<quint16>(5); // name length
456        ds << static_cast<quint16>(extra.size()); // extra length
457        ds.writeRawData("file", 4); // name
458        ds << static_cast<qint8>('0' + i); // name (contd.)
459        ds.writeRawData(extra.buffer(), extra.size());
460    }
461    // central dir:
462    qint64 centralStart = fakeLargeFile.pos();
463    for (int i = 0; i < numFiles; ++i) {
464        QBuffer extra;
465        extra.open(QIODevice::WriteOnly);
466        QDataStream es(&extra);
467        es.setByteOrder(QDataStream::LittleEndian);
468        // prepare extra
469        es << static_cast<quint16>(0x0001u); // zip64
470        es << static_cast<quint16>(24); // extra data size
471        es << static_cast<quint64>(0); // uncompressed size
472        es << static_cast<quint64>(0); // compressed size
473        es << static_cast<quint64>(localOffsets[i]);
474        // now the central dir header
475        ds << static_cast<quint32>(0x02014b50u); // central magic
476        ds << static_cast<quint16>(45); // version made by
477        ds << static_cast<quint16>(45); // version needed
478        ds << static_cast<quint16>(0); // flags
479        ds << static_cast<quint16>(0); // method
480        ds << static_cast<quint16>(0); // time 00:00:00
481        ds << static_cast<quint16>(0x21); // date 1980-01-01
482        ds << static_cast<quint32>(0); // CRC-32
483        ds << static_cast<quint32>(0xFFFFFFFFu); // compressed size
484        ds << static_cast<quint32>(0xFFFFFFFFu); // uncompressed size
485        ds << static_cast<quint16>(5); // name length
486        ds << static_cast<quint16>(extra.size()); // extra length
487        ds << static_cast<quint16>(0); // comment length
488        ds << static_cast<quint16>(0); // disk number
489        ds << static_cast<quint16>(0); // internal attrs
490        ds << static_cast<quint32>(0); // external attrs
491        ds << static_cast<quint32>(0xFFFFFFFFu); // local offset
492        ds.writeRawData("file", 4); // name
493        ds << static_cast<qint8>('0' + i); // name (contd.)
494        ds.writeRawData(extra.buffer(), extra.size());
495    }
496    qint64 centralEnd = fakeLargeFile.pos();
497    // zip64 end
498    ds << static_cast<quint32>(0x06064b50); // zip64 end magic
499    ds << static_cast<quint64>(44); // size of the zip64 end
500    ds << static_cast<quint16>(45); // version made by
501    ds << static_cast<quint16>(45); // version needed
502    ds << static_cast<quint32>(0); // disk number
503    ds << static_cast<quint32>(0); // central dir disk number
504    ds << static_cast<quint64>(2); // number of entries on disk
505    ds << static_cast<quint64>(2); // total number of entries
506    ds << static_cast<quint64>(centralEnd - centralStart); // size
507    ds << static_cast<quint64>(centralStart); // offset
508    // zip64 locator
509    ds << static_cast<quint32>(0x07064b50); // zip64 locator magic
510    ds << static_cast<quint32>(0); // disk number
511    ds << static_cast<quint64>(centralEnd); // offset
512    ds << static_cast<quint32>(1); // number of disks
513    // zip32 end
514    ds << static_cast<quint32>(0x06054b50); // end magic
515    ds << static_cast<quint16>(0); // disk number
516    ds << static_cast<quint16>(0); // central dir disk number
517    ds << static_cast<quint16>(2); // number of entries
518    ds << static_cast<quint32>(0xFFFFFFFFu); // central dir size
519    ds << static_cast<quint32>(0xFFFFFFFFu); // central dir offset
520    ds << static_cast<quint16>(0); // comment length
521    fakeLargeFile.close();
522    QuaZip fakeLargeZip("tmp/large.zip");
523    QVERIFY(fakeLargeZip.open(QuaZip::mdUnzip));
524    QCOMPARE(fakeLargeZip.getFileInfoList().size(), numFiles);
525    QCOMPARE(fakeLargeZip.getFileInfoList()[0].uncompressedSize,
526            static_cast<quint32>(0));
527    fakeLargeZip.close();
528    curDir.remove("tmp/large.zip");
529}
Note: See TracBrowser for help on using the repository browser.