1 /*
2 Copyright (C) 2005-2014 Sergey A. Tachenov
3
4 This file is part of QuaZip test suite.
5
6 QuaZip is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 2.1 of the License, or
9 (at your option) any later version.
10
11 QuaZip is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with QuaZip. If not, see <http://www.gnu.org/licenses/>.
18
19 See COPYING file for the full LGPL text.
20
21 Original ZIP package is copyrighted by Gilles Vollant and contributors,
22 see quazip/(un)zip.h files for details. Basically it's the zlib license.
23 */
24
25 #include "testquazip.h"
26
27 #include "qztest.h"
28
29 #include <QtCore/QDataStream>
30 #include <QtCore/QDir>
31 #include <QtCore/QFileInfo>
32 #include <QtCore/QHash>
33 #ifdef QUAZIP_TEST_QSAVEFILE
34 #include <QtCore/QSaveFile>
35 #endif
36 #include <QtNetwork/QTcpServer>
37 #include <QtNetwork/QTcpSocket>
38 #include <quazip_qt_compat.h>
39
40 #include <QtTest/QtTest>
41
42 #include <quazip.h>
43 #include <JlCompress.h>
44
getFileList_data()45 void TestQuaZip::getFileList_data()
46 {
47 QTest::addColumn<QString>("zipName");
48 QTest::addColumn<QStringList>("fileNames");
49 QTest::newRow("simple") << "qzfilelist.zip" << (
50 QStringList() << "test0.txt" << "testdir1/test1.txt"
51 << "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt");
52 QTest::newRow("russian") << QString::fromUtf8("файл.zip") << (
53 QStringList() << QString::fromUtf8("test0.txt") << QString::fromUtf8("test1/test1.txt")
54 << "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt");
55 QTest::newRow("japanese") << QString::fromUtf8("テスト.zip") << (
56 QStringList() << QString::fromUtf8("test.txt"));
57 QTest::newRow("hebrew") << QString::fromUtf8("פתח תקווה.zip") << (
58 QStringList() << QString::fromUtf8("test.txt"));
59 }
60
getFileList()61 void TestQuaZip::getFileList()
62 {
63 QFETCH(QString, zipName);
64 QFETCH(QStringList, fileNames);
65 fileNames.sort();
66 QDir curDir;
67 if (curDir.exists(zipName)) {
68 if (!curDir.remove(zipName))
69 QFAIL("Can't remove zip file");
70 }
71 if (!createTestFiles(fileNames)) {
72 QFAIL("Can't create test file");
73 }
74 if (!createTestArchive(zipName, fileNames)) {
75 QFAIL("Can't create test archive");
76 }
77 QuaZip testZip(zipName);
78 QVERIFY(testZip.open(QuaZip::mdUnzip));
79 QVERIFY(testZip.goToFirstFile());
80 QString firstFile = testZip.getCurrentFileName();
81 QStringList fileList = testZip.getFileNameList();
82 fileList.sort();
83 QCOMPARE(fileList, fileNames);
84 QHash<QString, QFileInfo> srcInfo;
85 foreach (QString fileName, fileNames) {
86 srcInfo[fileName] = QFileInfo("tmp/" + fileName);
87 }
88 QList<QuaZipFileInfo> destList = testZip.getFileInfoList();
89 QCOMPARE(destList.size(), srcInfo.size());
90 for (int i = 0; i < destList.size(); i++) {
91 QCOMPARE(static_cast<qint64>(destList[i].uncompressedSize),
92 srcInfo[destList[i].name].size());
93 }
94 // Now test zip64
95 QList<QuaZipFileInfo64> destList64 = testZip.getFileInfoList64();
96 QCOMPARE(destList64.size(), srcInfo.size());
97 for (int i = 0; i < destList64.size(); i++) {
98 QCOMPARE(static_cast<qint64>(destList64[i].uncompressedSize),
99 srcInfo[destList64[i].name].size());
100 }
101 // test that we didn't mess up the current file
102 QCOMPARE(testZip.getCurrentFileName(), firstFile);
103 testZip.close();
104 // clean up
105 removeTestFiles(fileNames);
106 curDir.remove(zipName);
107 }
108
add_data()109 void TestQuaZip::add_data()
110 {
111 QTest::addColumn<QString>("zipName");
112 QTest::addColumn<QStringList>("fileNames");
113 QTest::addColumn<QStringList>("fileNamesToAdd");
114 QTest::newRow("simple") << "qzadd.zip" << (
115 QStringList() << "test0.txt" << "testdir1/test1.txt"
116 << "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt")
117 << (QStringList() << "testAdd.txt");
118 }
119
add()120 void TestQuaZip::add()
121 {
122 QFETCH(QString, zipName);
123 QFETCH(QStringList, fileNames);
124 QFETCH(QStringList, fileNamesToAdd);
125 QDir curDir;
126 if (curDir.exists(zipName)) {
127 if (!curDir.remove(zipName))
128 QFAIL("Can't remove zip file");
129 }
130 if (!createTestFiles(fileNames)) {
131 QFAIL("Can't create test file");
132 }
133 if (!createTestArchive(zipName, fileNames)) {
134 QFAIL("Can't create test archive");
135 }
136 if (!createTestFiles(fileNamesToAdd)) {
137 QFAIL("Can't create test files to add");
138 }
139 QuaZip testZip(zipName);
140 QVERIFY(testZip.open(QuaZip::mdUnzip));
141 // according to the bug #3485459 the global is lost, so we test it
142 QString globalComment = testZip.getComment();
143 testZip.close();
144 QVERIFY(testZip.open(QuaZip::mdAdd));
145 foreach (QString fileName, fileNamesToAdd) {
146 QuaZipFile testFile(&testZip);
147 QVERIFY(testFile.open(QIODevice::WriteOnly,
148 QuaZipNewInfo(fileName, "tmp/" + fileName)));
149 QFile inFile("tmp/" + fileName);
150 QVERIFY(inFile.open(QIODevice::ReadOnly));
151 testFile.write(inFile.readAll());
152 inFile.close();
153 testFile.close();
154 }
155 testZip.close();
156 QVERIFY(testZip.open(QuaZip::mdUnzip));
157 QStringList allNames = fileNames + fileNamesToAdd;
158 QCOMPARE(testZip.getEntriesCount(), allNames.size());
159 QCOMPARE(testZip.getFileNameList(), allNames);
160 QCOMPARE(testZip.getComment(), globalComment);
161 testZip.close();
162 removeTestFiles(fileNames);
163 removeTestFiles(fileNamesToAdd);
164 curDir.remove(zipName);
165 }
166
setFileNameCodec_data()167 void TestQuaZip::setFileNameCodec_data()
168 {
169 QTest::addColumn<QString>("zipName");
170 QTest::addColumn<QStringList>("fileNames");
171 QTest::addColumn<QByteArray>("encoding");
172 QTest::newRow("russian") << QString::fromUtf8("russian.zip") << (
173 QStringList() << QString::fromUtf8("тест.txt")) << QByteArray("IBM866");
174 }
175
setFileNameCodec()176 void TestQuaZip::setFileNameCodec()
177 {
178 QFETCH(QString, zipName);
179 QFETCH(QStringList, fileNames);
180 QFETCH(QByteArray, encoding);
181 fileNames.sort();
182 QDir curDir;
183 if (curDir.exists(zipName)) {
184 if (!curDir.remove(zipName))
185 QFAIL("Can't remove zip file");
186 }
187 if (!createTestFiles(fileNames)) {
188 QFAIL("Can't create test file");
189 }
190 if (!createTestArchive(zipName, fileNames,
191 QTextCodec::codecForName(encoding))) {
192 QFAIL("Can't create test archive");
193 }
194 QuaZip testZip(zipName);
195 QVERIFY(testZip.open(QuaZip::mdUnzip));
196 QStringList fileList = testZip.getFileNameList();
197 fileList.sort();
198 QVERIFY(fileList[0] != fileNames[0]);
199 testZip.close();
200 testZip.setFileNameCodec(encoding);
201 QVERIFY(testZip.open(QuaZip::mdUnzip));
202 fileList = testZip.getFileNameList();
203 fileList.sort();
204 QCOMPARE(fileList, fileNames);
205 testZip.close();
206 // clean up
207 removeTestFiles(fileNames);
208 curDir.remove(zipName);
209 }
210
setOsCode_data()211 void TestQuaZip::setOsCode_data()
212 {
213 QTest::addColumn<QString>("zipName");
214 QTest::addColumn<uint>("osCode");
215 QTest::newRow("unix") << "unix.zip" << 3u;
216 QTest::newRow("dos") << "dos.zip" << 0u;
217 }
218
setOsCode()219 void TestQuaZip::setOsCode()
220 {
221 QFETCH(QString, zipName);
222 QFETCH(uint, osCode);
223 QuaZip testZip(zipName);
224 testZip.setOsCode(osCode);
225 testZip.open(QuaZip::mdCreate);
226 QCOMPARE(testZip.getOsCode(), osCode);
227 QuaZipFile testZipFile(&testZip);
228 testZipFile.open(QIODevice::WriteOnly, QuaZipNewInfo("test.txt"));
229 testZipFile.close();
230 testZip.close();
231 QuaZip checkZip(zipName);
232 checkZip.open(QuaZip::mdUnzip);
233 checkZip.goToFirstFile();
234 QuaZipFileInfo64 fi;
235 QVERIFY(checkZip.getCurrentFileInfo(&fi));
236 QCOMPARE(static_cast<uint>(fi.versionCreated) >> 8, osCode);
237 checkZip.close();
238 QDir().remove(zipName);
239 }
240
setDataDescriptorWritingEnabled()241 void TestQuaZip::setDataDescriptorWritingEnabled()
242 {
243 QString zipName = "zip10.zip";
244 QDir curDir;
245 if (curDir.exists(zipName)) {
246 if (!curDir.remove(zipName))
247 QFAIL("Can't remove zip file");
248 }
249 QuaZip testZip(zipName);
250 testZip.setDataDescriptorWritingEnabled(false);
251 QVERIFY(testZip.open(QuaZip::mdCreate));
252 QuaZipFile testZipFile(&testZip);
253 QVERIFY(testZipFile.open(QIODevice::WriteOnly,
254 QuaZipNewInfo("vegetation_info.xml"), NULL, 0, 0));
255 QByteArray contents = "<vegetation_info version=\"4096\" />\n";
256 testZipFile.write(contents);
257 testZipFile.close();
258 testZip.close();
259 QuaZipFile readZipFile(zipName, "vegetation_info.xml");
260 QVERIFY(readZipFile.open(QIODevice::ReadOnly));
261 // Test that file is not compressed.
262 QCOMPARE(readZipFile.csize(), static_cast<qint64>(contents.size()));
263 readZipFile.close();
264 QCOMPARE(QFileInfo(zipName).size(), static_cast<qint64>(171));
265 QFile zipFile(zipName);
266 QVERIFY(zipFile.open(QIODevice::ReadOnly));
267 QDataStream zipData(&zipFile);
268 zipData.setByteOrder(QDataStream::LittleEndian);
269 quint32 magic = 0;
270 quint16 versionNeeded = 0;
271 zipData >> magic;
272 zipData >> versionNeeded;
273 QCOMPARE(magic, static_cast<quint32>(0x04034b50));
274 QCOMPARE(versionNeeded, static_cast<quint16>(10));
275 zipFile.close();
276 curDir.remove(zipName);
277 // now test 2.0
278 zipName = "zip20.zip";
279 if (curDir.exists(zipName)) {
280 if (!curDir.remove(zipName))
281 QFAIL("Can't remove zip file");
282 }
283 QuaZip testZip20(zipName);
284 QVERIFY(testZip20.open(QuaZip::mdCreate));
285 QuaZipFile testZipFile20(&testZip20);
286 QVERIFY(testZipFile20.open(QIODevice::WriteOnly,
287 QuaZipNewInfo("vegetation_info.xml"), NULL, 0, 0));
288 testZipFile20.write("<vegetation_info version=\"4096\" />\n");
289 testZipFile20.close();
290 testZip20.close();
291 QCOMPARE(QFileInfo(zipName).size(),
292 static_cast<qint64>(171 + 16)); // 16 bytes = data descriptor
293 QFile zipFile20(zipName);
294 QVERIFY(zipFile20.open(QIODevice::ReadOnly));
295 QDataStream zipData20(&zipFile20);
296 zipData20.setByteOrder(QDataStream::LittleEndian);
297 magic = 0;
298 versionNeeded = 0;
299 zipData20 >> magic;
300 zipData20 >> versionNeeded;
301 QCOMPARE(magic, static_cast<quint32>(0x04034b50));
302 QCOMPARE(versionNeeded, static_cast<quint16>(20));
303 zipFile20.close();
304 curDir.remove(zipName);
305 }
306
testQIODeviceAPI()307 void TestQuaZip::testQIODeviceAPI()
308 {
309 QString zipName = "qiodevice_api.zip";
310 QStringList fileNames;
311 fileNames << "test.txt";
312 QDir curDir;
313 if (curDir.exists(zipName)) {
314 if (!curDir.remove(zipName))
315 QFAIL("Can't remove zip file");
316 }
317 if (!createTestFiles(fileNames)) {
318 QFAIL("Can't create test file");
319 }
320 if (!createTestArchive(zipName, fileNames)) {
321 QFAIL("Can't create test archive");
322 }
323 QBuffer buffer;
324 if (!createTestArchive(&buffer, fileNames, NULL)) {
325 QFAIL("Can't create test archive");
326 }
327 QFile diskFile(zipName);
328 QVERIFY(diskFile.open(QIODevice::ReadOnly));
329 QByteArray bufferArray = buffer.buffer();
330 QByteArray fileArray = diskFile.readAll();
331 diskFile.close();
332 QCOMPARE(bufferArray.size(), fileArray.size());
333 QCOMPARE(bufferArray, fileArray);
334 curDir.remove(zipName);
335 }
336
setZipName()337 void TestQuaZip::setZipName()
338 {
339 QuaZip zip;
340 zip.setZipName("testSetZipName.zip");
341 zip.open(QuaZip::mdCreate);
342 zip.close();
343 QVERIFY(QFileInfo(zip.getZipName()).exists());
344 QDir().remove(zip.getZipName());
345 }
346
setIoDevice()347 void TestQuaZip::setIoDevice()
348 {
349 QuaZip zip;
350 QFile file("testSetIoDevice.zip");
351 zip.setIoDevice(&file);
352 QCOMPARE(zip.getIoDevice(), &file);
353 zip.open(QuaZip::mdCreate);
354 QVERIFY(file.isOpen());
355 zip.close();
356 QVERIFY(!file.isOpen());
357 QVERIFY(file.exists());
358 QDir().remove(file.fileName());
359 }
360
setCommentCodec()361 void TestQuaZip::setCommentCodec()
362 {
363 QuaZip zip("commentCodec.zip");
364 QVERIFY(zip.open(QuaZip::mdCreate));
365 zip.setCommentCodec("WINDOWS-1251");
366 zip.setComment(QString::fromUtf8("Вопрос"));
367 QuaZipFile zipFile(&zip);
368 QVERIFY(zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo("test.txt")));
369 zipFile.close();
370 zip.close();
371 QVERIFY(zip.open(QuaZip::mdUnzip));
372 zip.setCommentCodec(QTextCodec::codecForName("KOI8-R"));
373 QCOMPARE(zip.getComment(), QString::fromUtf8("бНОПНЯ"));
374 zip.close();
375 QDir().remove(zip.getZipName());
376 }
377
setAutoClose()378 void TestQuaZip::setAutoClose()
379 {
380 {
381 QBuffer buf;
382 QuaZip zip(&buf);
383 QVERIFY(zip.isAutoClose());
384 QVERIFY(zip.open(QuaZip::mdCreate));
385 QVERIFY(buf.isOpen());
386 zip.close();
387 QVERIFY(!buf.isOpen());
388 QVERIFY(zip.open(QuaZip::mdCreate));
389 }
390 {
391 QBuffer buf;
392 QuaZip zip(&buf);
393 QVERIFY(zip.isAutoClose());
394 zip.setAutoClose(false);
395 QVERIFY(!zip.isAutoClose());
396 QVERIFY(zip.open(QuaZip::mdCreate));
397 QVERIFY(buf.isOpen());
398 zip.close();
399 QVERIFY(buf.isOpen());
400 QVERIFY(zip.open(QuaZip::mdCreate));
401 }
402 }
403
404 #ifdef QUAZIP_TEST_QSAVEFILE
saveFileBug()405 void TestQuaZip::saveFileBug()
406 {
407 QDir curDir;
408 QString zipName = "testSaveFile.zip";
409 if (curDir.exists(zipName)) {
410 if (!curDir.remove(zipName)) {
411 QFAIL("Can't remove testSaveFile.zip");
412 }
413 }
414 QuaZip zip;
415 QSaveFile saveFile(zipName);
416 zip.setIoDevice(&saveFile);
417 QCOMPARE(zip.getIoDevice(), &saveFile);
418 zip.open(QuaZip::mdCreate);
419 zip.close();
420 QVERIFY(QFileInfo(saveFile.fileName()).exists());
421 curDir.remove(saveFile.fileName());
422 }
423 #endif
424
testSequential()425 void TestQuaZip::testSequential()
426 {
427 QTcpServer server;
428 QVERIFY(server.listen(QHostAddress(QHostAddress::LocalHost)));
429 quint16 port = server.serverPort();
430 QTcpSocket socket;
431 socket.connectToHost(QHostAddress(QHostAddress::LocalHost), port);
432 QVERIFY(socket.waitForConnected());
433 QVERIFY(server.waitForNewConnection(30000));
434 QTcpSocket *client = server.nextPendingConnection();
435 QuaZip zip(&socket);
436 zip.setAutoClose(false);
437 QVERIFY(zip.open(QuaZip::mdCreate));
438 QVERIFY(socket.isOpen());
439 QuaZipFile zipFile(&zip);
440 QuaZipNewInfo info("test.txt");
441 QVERIFY(zipFile.open(QIODevice::WriteOnly, info, NULL, 0, 0));
442 QCOMPARE(zipFile.write("test"), static_cast<qint64>(4));
443 zipFile.close();
444 zip.close();
445 QVERIFY(socket.isOpen());
446 socket.disconnectFromHost();
447 QVERIFY(socket.waitForDisconnected());
448 QVERIFY(client->waitForReadyRead());
449 QByteArray received = client->readAll();
450 #ifdef QUAZIP_QZTEST_QUAZIP_DEBUG_SOCKET
451 QFile debug("testSequential.zip");
452 debug.open(QIODevice::WriteOnly);
453 debug.write(received);
454 debug.close();
455 #endif
456 client->close();
457 QBuffer buffer(&received);
458 QuaZip receivedZip(&buffer);
459 QVERIFY(receivedZip.open(QuaZip::mdUnzip));
460 QVERIFY(receivedZip.goToFirstFile());
461 QuaZipFileInfo64 receivedInfo;
462 QVERIFY(receivedZip.getCurrentFileInfo(&receivedInfo));
463 QCOMPARE(receivedInfo.name, QString::fromLatin1("test.txt"));
464 QCOMPARE(receivedInfo.uncompressedSize, static_cast<quint64>(4));
465 QuaZipFile receivedFile(&receivedZip);
466 QVERIFY(receivedFile.open(QIODevice::ReadOnly));
467 QByteArray receivedText = receivedFile.readAll();
468 QCOMPARE(receivedText, QByteArray("test"));
469 receivedFile.close();
470 receivedZip.close();
471 }
472