Commit 4d0eaefc authored by Elvis Angelaccio's avatar Elvis Angelaccio
Browse files

Merge branch 'gsoc2016/master'

This commit merges the work done by Vladyslav Batyrenko during the Google
Summer of Code 2016 program.

Cut, copy, paste and rename functionalities are now implemented.
It is also possible to add new files to a specific folder in an archive.

More information about the project here: https://community.kde.org/GSoC/2016/StatusReports/Batyrenko_Vladyslav

CCMAIL: mvlabat@gmail.com

GUI:

FEATURE: 65576
FEATURE: 181749
FEATURE: 234375
FIXED-IN: 16.12.0

Task: T917
parents 102b305a 7eb3304d
sudo: required
language: cpp
compiler:
- gcc
- clang
arch:
packages:
- extra-cmake-modules
- kdoctools
- python
- kparts
- kpty
- libarchive
- hicolor-icon-theme
- p7zip
- unzip
- zip
- lrzip
# for GUI tests
- xorg-server-xvfb
# from AUR:
- rar
- unarchiver
script:
- "cmake -DCMAKE_BUILD_TYPE=Debug -DKDE_INSTALL_LIBDIR=lib -DKDE_INSTALL_USE_QT_SYS_PATHS=ON -DCMAKE_INSTALL_PREFIX=/usr ."
- "make"
- "sudo make install"
# run the tests using the xvfb-run wrapper
- "xvfb-run --auto-servernum ctest --output-on-failure"
script:
- "curl -s https://raw.githubusercontent.com/mikkeloscar/arch-travis/master/arch-travis.sh | bash"
......@@ -92,7 +92,7 @@ void BatchExtract::addExtraction(Kerfuffle::Archive* archive)
Kerfuffle::ExtractionOptions options;
options[QStringLiteral("PreservePaths")] = preservePaths();
Kerfuffle::ExtractJob *job = archive->copyFiles(QVariantList(), destination, options);
Kerfuffle::ExtractJob *job = archive->extractFiles(QList<Kerfuffle::Archive::Entry*>(), destination, options);
qCDebug(ARK) << QString(QStringLiteral("Registering job from archive %1, to %2, preservePaths %3")).arg(archive->fileName(), destination, QString::number(preservePaths()));
......
include(ECMAddTests)
add_subdirectory(app)
add_subdirectory(testhelper)
add_subdirectory(kerfuffle)
add_subdirectory(plugins)
......@@ -9,11 +9,14 @@ target_link_libraries(jsoninterface kerfuffle)
ecm_add_tests(
addtoarchivetest.cpp
archivetest.cpp
extracttest.cpp
addtest.cpp
movetest.cpp
copytest.cpp
createdialogtest.cpp
metadatatest.cpp
mimetypetest.cpp
LINK_LIBRARIES kerfuffle Qt5::Test
LINK_LIBRARIES testhelper kerfuffle Qt5::Test
NAME_PREFIX kerfuffle-)
ecm_add_test(
......
/*
* Copyright (c) 2016 Vladyslav Batyrenko <mvlabat@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "autotests/testhelper/testhelper.h"
using namespace Kerfuffle;
class AddTest : public QObject
{
Q_OBJECT
private:
void addAllFormatsRows(const QString testName, const QString archiveName, QList<Archive::Entry*> entries, Archive::Entry *destination) {
QStringList formats = QStringList()
<< QStringLiteral("7z")
<< QStringLiteral("rar")
<< QStringLiteral("tar.bz2")
<< QStringLiteral("zip");
foreach (QString format, formats) {
const QString testNameWithFormat = testName + QStringLiteral(" (") + format + QStringLiteral(")");
QTest::newRow(testNameWithFormat.toUtf8())
<< archiveName + QLatin1Char('.') + format
<< entries
<< destination;
}
}
private Q_SLOTS:
void testAdding_data();
void testAdding();
};
QTEST_GUILESS_MAIN(AddTest)
void AddTest::testAdding_data()
{
QTest::addColumn<QString>("archiveName");
QTest::addColumn<QList<Archive::Entry*>>("files");
QTest::addColumn<Archive::Entry*>("destination");
addAllFormatsRows(QStringLiteral("without destination"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("textfile1.txt")),
new Archive::Entry(this, QStringLiteral("textfile2.txt")),
},
new Archive::Entry(this));
addAllFormatsRows(QStringLiteral("with destination, files"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("textfile1.txt")),
new Archive::Entry(this, QStringLiteral("textfile2.txt")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
addAllFormatsRows(QStringLiteral("with destination, directory"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("testdir/")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
addAllFormatsRows(QStringLiteral("without destination, directory 2"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("testdir2/")),
},
new Archive::Entry(this));
addAllFormatsRows(QStringLiteral("with destination, directory 2"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("testdir2/")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
}
void AddTest::testAdding()
{
QTemporaryDir temporaryDir;
QFETCH(QString, archiveName);
const QString archivePath = temporaryDir.path() + QLatin1Char('/') + archiveName;
Q_ASSERT(QFile::copy(QFINDTESTDATA(QStringLiteral("data/") + archiveName), archivePath));
Archive *archive = Archive::create(archivePath, this);
QVERIFY(archive);
if (!archive->isValid()) {
QSKIP("Could not find a plugin to handle the archive. Skipping test.", SkipSingle);
}
QFETCH(QList<Archive::Entry*>, files);
QFETCH(Archive::Entry*, destination);
QList<Archive::Entry*> oldEntries = TestHelper::getEntryList(archive);
CompressionOptions options = CompressionOptions();
options.insert(QStringLiteral("GlobalWorkDir"), QFINDTESTDATA("data"));
AddJob *addJob = archive->addFiles(files, destination, options);
TestHelper::startAndWaitForResult(addJob);
QList<Archive::Entry*> resultedEntries = TestHelper::getEntryList(archive);
TestHelper::verifyAddedEntriesWithDestination(files, destination, oldEntries, resultedEntries);
archive->deleteLater();
}
#include "addtest.moc"
......@@ -43,6 +43,7 @@ private Q_SLOTS:
void init();
void testCompressHere_data();
void testCompressHere();
void testCreateEncryptedArchive();
};
void AddToArchiveTest::init()
......@@ -232,6 +233,23 @@ void AddToArchiveTest::testCompressHere()
QVERIFY(QFile(archive->fileName()).remove());
}
void AddToArchiveTest::testCreateEncryptedArchive()
{
Archive *archive = Archive::create(QStringLiteral("foo.zip"));
QVERIFY(archive);
if (!archive->isValid()) {
QSKIP("Could not find a plugin to handle the archive. Skipping test.", SkipSingle);
}
QCOMPARE(archive->encryptionType(), Archive::Unencrypted);
archive->encrypt(QStringLiteral("1234"), false);
QCOMPARE(archive->encryptionType(), Archive::Encrypted);
archive->deleteLater();
}
QTEST_MAIN(AddToArchiveTest)
#include "addtoarchivetest.moc"
/*
* Copyright (c) 2016 Vladyslav Batyrenko <mvlabat@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "autotests/testhelper/testhelper.h"
using namespace Kerfuffle;
class CopyTest : public QObject
{
Q_OBJECT
private:
void addAllFormatsRows(const QString testName, const QString archiveName, QList<Archive::Entry*> entries, Archive::Entry *destination) {
QStringList formats = QStringList()
<< QStringLiteral("7z")
<< QStringLiteral("rar")
<< QStringLiteral("tar.bz2")
<< QStringLiteral("zip");
foreach (QString format, formats) {
const QString testNameWithFormat = testName + QStringLiteral(" (") + format + QStringLiteral(")");
QTest::newRow(testNameWithFormat.toUtf8())
<< archiveName + QLatin1Char('.') + format
<< entries
<< destination;
}
}
private Q_SLOTS:
void testCopying_data();
void testCopying();
};
QTEST_GUILESS_MAIN(CopyTest)
void CopyTest::testCopying_data()
{
QTest::addColumn<QString>("archiveName");
QTest::addColumn<QList<Archive::Entry*>>("files");
QTest::addColumn<Archive::Entry*>("destination");
addAllFormatsRows(QStringLiteral("copy a single file"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("a.txt")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
addAllFormatsRows(QStringLiteral("copy several files"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("a.txt")),
new Archive::Entry(this, QStringLiteral("b.txt")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
addAllFormatsRows(QStringLiteral("copy a root directory"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("dir1/")),
new Archive::Entry(this, QStringLiteral("dir1/dir/")),
new Archive::Entry(this, QStringLiteral("dir1/dir/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/dir/b.txt")),
new Archive::Entry(this, QStringLiteral("dir1/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/b.txt")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
addAllFormatsRows(QStringLiteral("copy a root directory 2"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("dir2/")),
new Archive::Entry(this, QStringLiteral("dir2/dir/")),
new Archive::Entry(this, QStringLiteral("dir2/dir/a.txt")),
new Archive::Entry(this, QStringLiteral("dir2/dir/b.txt")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
addAllFormatsRows(QStringLiteral("copy a root directory 3"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("dir2/")),
new Archive::Entry(this, QStringLiteral("dir2/dir/")),
new Archive::Entry(this, QStringLiteral("dir2/dir/a.txt")),
new Archive::Entry(this, QStringLiteral("dir2/dir/b.txt")),
},
new Archive::Entry(this, QStringLiteral("dir1/")));
addAllFormatsRows(QStringLiteral("copy a directory"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("dir1/dir/")),
new Archive::Entry(this, QStringLiteral("dir1/dir/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/dir/b.txt")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
addAllFormatsRows(QStringLiteral("copy several directories"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("dir1/")),
new Archive::Entry(this, QStringLiteral("dir1/dir/")),
new Archive::Entry(this, QStringLiteral("dir1/dir/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/dir/b.txt")),
new Archive::Entry(this, QStringLiteral("dir1/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/b.txt")),
new Archive::Entry(this, QStringLiteral("dir2/")),
new Archive::Entry(this, QStringLiteral("dir2/dir/")),
new Archive::Entry(this, QStringLiteral("dir2/dir/a.txt")),
new Archive::Entry(this, QStringLiteral("dir2/dir/b.txt")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
addAllFormatsRows(QStringLiteral("copy several entries"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("dir1/dir/")),
new Archive::Entry(this, QStringLiteral("dir1/dir/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/dir/b.txt")),
new Archive::Entry(this, QStringLiteral("dir1/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/b.txt")),
},
new Archive::Entry(this, QStringLiteral("empty_dir/")));
addAllFormatsRows(QStringLiteral("copy a directory inside itself"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("dir1/")),
new Archive::Entry(this, QStringLiteral("dir1/dir/")),
new Archive::Entry(this, QStringLiteral("dir1/dir/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/dir/b.txt")),
new Archive::Entry(this, QStringLiteral("dir1/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/b.txt")),
},
new Archive::Entry(this, QStringLiteral("dir1/")));
addAllFormatsRows(QStringLiteral("copy a directory to the root"),
QStringLiteral("test"),
QList<Archive::Entry*> {
new Archive::Entry(this, QStringLiteral("dir1/dir/")),
new Archive::Entry(this, QStringLiteral("dir1/dir/a.txt")),
new Archive::Entry(this, QStringLiteral("dir1/dir/b.txt")),
},
new Archive::Entry(this, QStringLiteral("")));
}
void CopyTest::testCopying()
{
QTemporaryDir temporaryDir;
QFETCH(QString, archiveName);
const QString archivePath = temporaryDir.path() + QLatin1Char('/') + archiveName;
Q_ASSERT(QFile::copy(QFINDTESTDATA(QStringLiteral("data/") + archiveName), archivePath));
Archive *archive = Archive::create(archivePath, this);
QVERIFY(archive);
if (!archive->isValid()) {
QSKIP("Could not find a plugin to handle the archive. Skipping test.", SkipSingle);
}
QFETCH(QList<Archive::Entry*>, files);
QFETCH(Archive::Entry*, destination);
const QList<Archive::Entry*> oldEntries = TestHelper::getEntryList(archive);
CompressionOptions options = CompressionOptions();
options.insert(QStringLiteral("GlobalWorkDir"), QFINDTESTDATA("data"));
CopyJob *copyJob = archive->copyFiles(files, destination, options);
TestHelper::startAndWaitForResult(copyJob);
QList<Archive::Entry*> resultedEntries = TestHelper::getEntryList(archive);
TestHelper::verifyCopiedEntriesWithDestination(files, destination, oldEntries, resultedEntries);
archive->deleteLater();
}
#include "copytest.moc"
[
{
"FileName": "aDir/",
"IsDirectory": true
"fullPath": "aDir/",
"isDirectory": true
},
{
"FileName": "aDir/b.txt"
"fullPath": "aDir/b.txt"
},
{
"FileName": "aDir/aDirInside/",
"IsDirectory": true
"fullPath": "aDir/aDirInside/",
"isDirectory": true
},
{
"FileName": "aDir/aDirInside/anotherDir/",
"IsDirectory": true
"fullPath": "aDir/aDirInside/anotherDir/",
"isDirectory": true
},
{
"FileName": "aDir/aDirInside/anotherDir/file.txt"
"fullPath": "aDir/aDirInside/anotherDir/file.txt"
}
]
[
{
"FileName": "aDir/",
"IsDirectory": true
"fullPath": "aDir/",
"isDirectory": true
}
]
[
{
"FileName": "aDir/",
"IsDirectory": true
"fullPath": "aDir/",
"isDirectory": true
},
{
"FileName": "aDir/b.txt"
"fullPath": "aDir/b.txt"
},
{
"FileName": "anotherDir/",
"IsDirectory": true
"fullPath": "anotherDir/",
"isDirectory": true
},
{
"FileName": "anotherDir/..",
"IsDirectory": true
"fullPath": "anotherDir/..",
"isDirectory": true
},
{
"FileName": "anotherDir/../..",
"IsDirectory": true
"fullPath": "anotherDir/../..",
"isDirectory": true
},
{
"FileName": "anotherDir/../../file.txt"
"fullPath": "anotherDir/../../file.txt"
}
]
[
{
"FileName": "aDir/",
"IsDirectory": true
"fullPath": "aDir/",
"isDirectory": true
},
{
"FileName": "aDir/b.txt"
"fullPath": "aDir/b.txt"
},
{
"FileName": "anotherDir/",
"IsDirectory": true
"fullPath": "anotherDir/",
"isDirectory": true
},
{
"FileName": "anotherDir/file.txt"
"fullPath": "anotherDir/file.txt"
}
]
[
{
"FileName": "a.txt"
"fullPath": "a.txt"
},
{
"FileName": "file.txt"
"fullPath": "file.txt"
}
]
[
{
"FileName": "aDir/",
"IsDirectory": true
"fullPath": "aDir/",
"isDirectory": true
},
{
"FileName": "aDir/b.txt"
"fullPath": "aDir/b.txt"
}
]
[
{
"FileName": "foo.txt",
"IsPasswordProtected": true
"fullPath": "foo.txt",
"isPasswordProtected": true
},
{
"FileName": "bar.txt"
"fullPath": "bar.txt"
},
{
"FileName": "aD