You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
547 lines
15 KiB
547 lines
15 KiB
8 years ago
|
/*
|
||
|
Copyright (c) 2014, Lukas Holecek <hluk@email.cz>
|
||
|
|
||
|
This file is part of CopyQ.
|
||
|
|
||
|
CopyQ is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
CopyQ 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 General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with CopyQ. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "itemsynctests.h"
|
||
|
|
||
|
#include "common/mimetypes.h"
|
||
|
#include "tests/test_utils.h"
|
||
|
|
||
|
#include <QDir>
|
||
|
#include <QFile>
|
||
|
|
||
|
#include <memory>
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
using FilePtr = std::shared_ptr<QFile>;
|
||
|
|
||
|
const char sep[] = " ;; ";
|
||
|
|
||
|
QString fileNameForId(int i)
|
||
|
{
|
||
|
return QString("copyq_%1.txt").arg(i, 4, 10, QChar('0'));
|
||
|
}
|
||
|
|
||
|
class TestDir {
|
||
|
public:
|
||
|
explicit TestDir(int i, bool createPath = true)
|
||
|
: m_dir(ItemSyncTests::testDir(i))
|
||
|
{
|
||
|
clear();
|
||
|
if (createPath)
|
||
|
create();
|
||
|
}
|
||
|
|
||
|
~TestDir()
|
||
|
{
|
||
|
clear();
|
||
|
}
|
||
|
|
||
|
void clear()
|
||
|
{
|
||
|
if (isValid()) {
|
||
|
for ( const auto &fileName : files() )
|
||
|
remove(fileName);
|
||
|
m_dir.rmpath(".");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void create()
|
||
|
{
|
||
|
if ( !m_dir.mkpath(".") )
|
||
|
Q_ASSERT(false);
|
||
|
}
|
||
|
|
||
|
bool isValid() const
|
||
|
{
|
||
|
return m_dir.exists();
|
||
|
}
|
||
|
|
||
|
QStringList files() const
|
||
|
{
|
||
|
return m_dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name);
|
||
|
}
|
||
|
|
||
|
FilePtr file(const QString &fileName) const
|
||
|
{
|
||
|
return std::make_shared<QFile>(filePath(fileName));
|
||
|
}
|
||
|
|
||
|
QString filePath(const QString &fileName) const
|
||
|
{
|
||
|
return m_dir.absoluteFilePath(fileName);
|
||
|
}
|
||
|
|
||
|
bool remove(const QString &fileName)
|
||
|
{
|
||
|
return QFile::remove(filePath(fileName));
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
Q_DISABLE_COPY(TestDir)
|
||
|
QDir m_dir;
|
||
|
};
|
||
|
|
||
|
QByteArray createFile(const TestDir &dir, const QString &fileName, const QByteArray &content)
|
||
|
{
|
||
|
FilePtr file(dir.file(fileName));
|
||
|
if ( file->exists() )
|
||
|
return "File already exists!";
|
||
|
|
||
|
if ( !file->open(QIODevice::WriteOnly) )
|
||
|
return "Cannot open file!";
|
||
|
|
||
|
if ( file->write(content) == -1 )
|
||
|
return "Cannot write to file!";
|
||
|
|
||
|
file->close();
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
ItemSyncTests::ItemSyncTests(const TestInterfacePtr &test, QObject *parent)
|
||
|
: QObject(parent)
|
||
|
, m_test(test)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
QString ItemSyncTests::testTab(int i)
|
||
|
{
|
||
|
return ::testTab(i);
|
||
|
}
|
||
|
|
||
|
QString ItemSyncTests::testDir(int i)
|
||
|
{
|
||
|
return QDir::tempPath() + "/copyq_test_dirs/itemsync_" + QString::number(i);
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::initTestCase()
|
||
|
{
|
||
|
TEST(m_test->initTestCase());
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::cleanupTestCase()
|
||
|
{
|
||
|
TEST(m_test->cleanupTestCase());
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::init()
|
||
|
{
|
||
|
TEST(m_test->init());
|
||
|
|
||
|
// Remove temporary directory.
|
||
|
for (int i = 0; i < 10; ++i)
|
||
|
TestDir(i, false);
|
||
|
|
||
|
QDir tmpDir(QDir::cleanPath(testDir(0) + "/.."));
|
||
|
if ( tmpDir.exists() )
|
||
|
QVERIFY(tmpDir.rmdir("."));
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::cleanup()
|
||
|
{
|
||
|
TEST( m_test->cleanup() );
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::createRemoveTestDir()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
TestDir dir2(2);
|
||
|
|
||
|
QVERIFY(dir1.isValid());
|
||
|
QCOMPARE(dir1.files().join(sep), QString());
|
||
|
|
||
|
QVERIFY(dir2.isValid());
|
||
|
QCOMPARE(dir2.files().join(sep), QString());
|
||
|
|
||
|
const QString testFileName1 = "test1.txt";
|
||
|
FilePtr f1(dir1.file(testFileName1));
|
||
|
QVERIFY(!f1->exists());
|
||
|
QVERIFY(f1->open(QIODevice::WriteOnly));
|
||
|
f1->close();
|
||
|
|
||
|
QCOMPARE(dir1.files().join(sep), testFileName1);
|
||
|
|
||
|
dir1.clear();
|
||
|
QVERIFY(!dir1.isValid());
|
||
|
QVERIFY(!f1->exists());
|
||
|
QVERIFY(dir2.isValid());
|
||
|
|
||
|
dir2.clear();
|
||
|
QVERIFY(!dir1.isValid());
|
||
|
QVERIFY(!dir2.isValid());
|
||
|
|
||
|
dir1.create();
|
||
|
QVERIFY(dir1.isValid());
|
||
|
QCOMPARE(dir2.files().join(sep), QString());
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::itemsToFiles()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
const QString tab1 = testTab(1);
|
||
|
const Args args = Args() << "tab" << tab1;
|
||
|
|
||
|
RUN(args << "add" << "A" << "B" << "C", "");
|
||
|
RUN(args << "read" << "0" << "1" << "2", "C\nB\nA");
|
||
|
RUN(args << "size", "3\n");
|
||
|
|
||
|
QCOMPARE( dir1.files().join(sep),
|
||
|
fileNameForId(0) + sep + fileNameForId(1) + sep + fileNameForId(2) );
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::filesToItems()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
const QString tab1 = testTab(1);
|
||
|
const Args args = Args() << "tab" << tab1;
|
||
|
|
||
|
RUN(args << "size", "0\n");
|
||
|
|
||
|
const QByteArray text1 = "Hello world!";
|
||
|
createFile(dir1, "test1.txt", text1);
|
||
|
|
||
|
QTest::qSleep(1200);
|
||
|
|
||
|
const QByteArray text2 = "And hello again!";
|
||
|
TEST(createFile(dir1, "test2.txt", text2));
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "size", "2\n");
|
||
|
// Newer files first.
|
||
|
RUN(args << "read" << "0", text2);
|
||
|
RUN(args << "read" << "1", text1);
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::removeOwnItems()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
const QString tab1 = testTab(1);
|
||
|
const Args args = Args() << "separator" << "," << "tab" << tab1;
|
||
|
|
||
|
RUN(args << "add" << "A" << "B" << "C" << "D", "");
|
||
|
|
||
|
const QString fileA = fileNameForId(0);
|
||
|
const QString fileB = fileNameForId(1);
|
||
|
const QString fileC = fileNameForId(2);
|
||
|
const QString fileD = fileNameForId(3);
|
||
|
|
||
|
QCOMPARE( dir1.files().join(sep),
|
||
|
fileA
|
||
|
+ sep + fileB
|
||
|
+ sep + fileC
|
||
|
+ sep + fileD
|
||
|
);
|
||
|
|
||
|
// Move to test tab and select second and third item.
|
||
|
RUN("setCurrentTab" << tab1, "");
|
||
|
RUN(args << "selectItems" << "1" << "2", "true\n");
|
||
|
RUN(args << "testSelected", tab1.toUtf8() + " 2 1 2\n");
|
||
|
|
||
|
// Remove selected items.
|
||
|
RUN(args << "keys" << m_test->shortcutToRemove(), "");
|
||
|
RUN(args << "read" << "0" << "1" << "2" << "3", "D,A,,");
|
||
|
QCOMPARE( dir1.files().join(sep),
|
||
|
fileA
|
||
|
+ sep + fileD
|
||
|
);
|
||
|
|
||
|
// Removing own items works from script.
|
||
|
RUN(args << "remove" << "1", "");
|
||
|
RUN(args << "read" << "0" << "1" << "2" << "3", "D,,,");
|
||
|
QCOMPARE( dir1.files().join(sep), fileD );
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::removeNotOwnedItems()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
const QString tab1 = testTab(1);
|
||
|
const Args args = Args() << "separator" << "," << "tab" << tab1;
|
||
|
|
||
|
const QString fileA = "test1.txt";
|
||
|
const QString fileB = "test2.txt";
|
||
|
const QString fileC = "test3.txt";
|
||
|
const QString fileD = "test4.txt";
|
||
|
|
||
|
TEST(createFile(dir1, fileA, "A"));
|
||
|
WAIT_ON_OUTPUT(args << "size", "1\n");
|
||
|
TEST(createFile(dir1, fileB, "B"));
|
||
|
WAIT_ON_OUTPUT(args << "size", "2\n");
|
||
|
TEST(createFile(dir1, fileC, "C"));
|
||
|
WAIT_ON_OUTPUT(args << "size", "3\n");
|
||
|
TEST(createFile(dir1, fileD, "D"));
|
||
|
WAIT_ON_OUTPUT(args << "size", "4\n");
|
||
|
|
||
|
QCOMPARE( dir1.files().join(sep),
|
||
|
fileA
|
||
|
+ sep + fileB
|
||
|
+ sep + fileC
|
||
|
+ sep + fileD
|
||
|
);
|
||
|
|
||
|
// Move to test tab and select second and third item.
|
||
|
RUN("setCurrentTab" << tab1, "");
|
||
|
RUN(args << "selectItems" << "1" << "2", "true\n");
|
||
|
RUN(args << "testSelected", tab1.toUtf8() + " 2 1 2\n");
|
||
|
|
||
|
// Don't accept the "Remove Items?" dialog.
|
||
|
RUN(args << "keys" << m_test->shortcutToRemove(), "");
|
||
|
RUN(args << "keys" << "ESCAPE", "");
|
||
|
RUN(args << "read" << "0" << "1" << "2" << "3", "D,C,B,A");
|
||
|
QCOMPARE( dir1.files().join(sep),
|
||
|
fileA
|
||
|
+ sep + fileB
|
||
|
+ sep + fileC
|
||
|
+ sep + fileD
|
||
|
);
|
||
|
|
||
|
// Accept the "Remove Items?" dialog.
|
||
|
RUN(args << "keys" << m_test->shortcutToRemove(), "");
|
||
|
RUN(args << "keys" << "ENTER", "");
|
||
|
RUN(args << "read" << "0" << "1" << "2" << "3", "D,A,,");
|
||
|
QCOMPARE( dir1.files().join(sep),
|
||
|
fileA
|
||
|
+ sep + fileD
|
||
|
);
|
||
|
|
||
|
// Removing not owned items from script doesn't work.
|
||
|
RUN_EXPECT_ERROR(args << "remove" << "1", CommandException);
|
||
|
QCOMPARE( dir1.files().join(sep),
|
||
|
fileA
|
||
|
+ sep + fileD
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::removeFiles()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
const QString tab1 = testTab(1);
|
||
|
const Args args = Args() << "separator" << "," << "tab" << tab1;
|
||
|
|
||
|
RUN(args << "add" << "A" << "B" << "C" << "D", "");
|
||
|
|
||
|
const QString fileA = fileNameForId(0);
|
||
|
const QString fileB = fileNameForId(1);
|
||
|
const QString fileC = fileNameForId(2);
|
||
|
const QString fileD = fileNameForId(3);
|
||
|
|
||
|
QCOMPARE( dir1.files().join(sep),
|
||
|
fileA
|
||
|
+ sep + fileB
|
||
|
+ sep + fileC
|
||
|
+ sep + fileD
|
||
|
);
|
||
|
|
||
|
FilePtr file = dir1.file(fileC);
|
||
|
QVERIFY(file->open(QIODevice::ReadOnly));
|
||
|
QCOMPARE(file->readAll().data(), QByteArray("C").data());
|
||
|
file->remove();
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "size", "3\n");
|
||
|
RUN(args << "read" << "0" << "1" << "2", "D,B,A");
|
||
|
|
||
|
dir1.file(fileB)->remove();
|
||
|
dir1.file(fileA)->remove();
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "size", "1\n");
|
||
|
RUN(args << "read" << "0", "D");
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::modifyItems()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
const QString tab1 = testTab(1);
|
||
|
const Args args = Args() << "separator" << "," << "tab" << tab1;
|
||
|
|
||
|
RUN(args << "add" << "A" << "B" << "C" << "D", "");
|
||
|
|
||
|
const QString fileC = fileNameForId(2);
|
||
|
FilePtr file = dir1.file(fileC);
|
||
|
QVERIFY(file->open(QIODevice::ReadOnly));
|
||
|
QCOMPARE(file->readAll().data(), QByteArray("C").data());
|
||
|
file->close();
|
||
|
|
||
|
RUN(args << "keys" << "RIGHT" << "HOME" << "DOWN" << "F2" << ":XXX" << "F2", "");
|
||
|
RUN(args << "size", "4\n");
|
||
|
RUN(args << "read" << "0" << "1" << "2" << "3", "D,XXX,B,A");
|
||
|
|
||
|
file = dir1.file(fileC);
|
||
|
QVERIFY(file->open(QIODevice::ReadOnly));
|
||
|
QCOMPARE(file->readAll().data(), QByteArray("XXX").data());
|
||
|
file->close();
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::modifyFiles()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
const QString tab1 = testTab(1);
|
||
|
const Args args = Args() << "separator" << "," << "tab" << tab1;
|
||
|
|
||
|
RUN(args << "add" << "A" << "B" << "C" << "D", "");
|
||
|
|
||
|
const QString fileA = fileNameForId(0);
|
||
|
const QString fileB = fileNameForId(1);
|
||
|
const QString fileC = fileNameForId(2);
|
||
|
const QString fileD = fileNameForId(3);
|
||
|
|
||
|
QCOMPARE( dir1.files().join(sep),
|
||
|
fileA
|
||
|
+ sep + fileB
|
||
|
+ sep + fileC
|
||
|
+ sep + fileD
|
||
|
);
|
||
|
|
||
|
FilePtr file = dir1.file(fileC);
|
||
|
QVERIFY(file->open(QIODevice::ReadWrite));
|
||
|
QCOMPARE(file->readAll().data(), QByteArray("C").data());
|
||
|
file->write("X");
|
||
|
file->close();
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "read" << "0" << "1" << "2" << "3", "D,CX,B,A");
|
||
|
RUN(args << "size", "4\n");
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::notes()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
const QString tab1 = testTab(1);
|
||
|
|
||
|
const Args args = Args() << "separator" << ";" << "tab" << tab1;
|
||
|
|
||
|
RUN(args << "add" << "TEST1", "");
|
||
|
|
||
|
RUN(args << "keys" << "LEFT"
|
||
|
<< "CTRL+N" << ":TEST2" << "F2"
|
||
|
<< "CTRL+N" << ":TEST3" << "F2", "");
|
||
|
RUN(args << "size", "3\n");
|
||
|
RUN(args << "read" << "0" << "1" << "2", "TEST3;TEST2;TEST1");
|
||
|
|
||
|
const QString fileTest1 = fileNameForId(0);
|
||
|
const QString fileTest2 = fileNameForId(1);
|
||
|
const QString fileTest3 = fileNameForId(2);
|
||
|
|
||
|
const QStringList files1 = QStringList() << fileTest1 << fileTest2 << fileTest3;
|
||
|
|
||
|
QCOMPARE( dir1.files().join(sep), files1.join(sep) );
|
||
|
|
||
|
RUN(args << "keys" << "HOME" << "DOWN" << "SHIFT+F2" << ":NOTE1" << "F2", "");
|
||
|
RUN(args << "read" << mimeItemNotes << "0" << "1" << "2", ";NOTE1;");
|
||
|
|
||
|
// One new file for notes.
|
||
|
const QStringList files2 = dir1.files();
|
||
|
const QSet<QString> filesDiff = files2.toSet() - files1.toSet();
|
||
|
QCOMPARE( filesDiff.size(), 1 );
|
||
|
const QString fileNote = *filesDiff.begin();
|
||
|
|
||
|
// Read file with the notes.
|
||
|
FilePtr file = dir1.file(fileNote);
|
||
|
QVERIFY(file->open(QIODevice::ReadWrite));
|
||
|
QCOMPARE(file->readAll().data(), QByteArray("NOTE1").data());
|
||
|
|
||
|
// Modify notes.
|
||
|
file->write("+NOTE2");
|
||
|
file->close();
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "read" << mimeItemNotes << "0" << "1" << "2", ";NOTE1+NOTE2;");
|
||
|
RUN(args << "size", "3\n");
|
||
|
|
||
|
// Remove notes.
|
||
|
QVERIFY(file->remove());
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "read" << mimeItemNotes << "0" << "1" << "2", ";;");
|
||
|
RUN(args << "size", "3\n");
|
||
|
}
|
||
|
|
||
|
void ItemSyncTests::customFormats()
|
||
|
{
|
||
|
TestDir dir1(1);
|
||
|
const QString tab1 = testTab(1);
|
||
|
const Args args = Args() << "separator" << ";" << "tab" << tab1;
|
||
|
|
||
|
const QByteArray data1 = "Custom format content";
|
||
|
createFile(dir1, "test1.xxx", data1);
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "size", "1\n");
|
||
|
RUN(args << "keys" << "LEFT", "");
|
||
|
RUN(args << "read" << COPYQ_MIME_PREFIX "test-xxx" << "0", data1);
|
||
|
|
||
|
const QByteArray data2 = "Other custom format content";
|
||
|
createFile(dir1, "test2.yyy", data2);
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "size", "2\n");
|
||
|
RUN(args << "read" << COPYQ_MIME_PREFIX "test-zzz" << "0", data2);
|
||
|
|
||
|
const QByteArray data3 = "Last custom format content";
|
||
|
createFile(dir1, "test3.zzz", data3);
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "size", "3\n");
|
||
|
RUN(args << "read" << COPYQ_MIME_PREFIX "test-zzz" << "0", data3);
|
||
|
|
||
|
RUN(args << "read" << COPYQ_MIME_PREFIX "test-xxx" << "0" << "1" << "2",
|
||
|
";;" + data1);
|
||
|
RUN(args << "read" << COPYQ_MIME_PREFIX "test-zzz" << "0" << "1" << "2",
|
||
|
data3 + ";" + data2 + ";");
|
||
|
RUN(args << "read" << COPYQ_MIME_PREFIX "test-zzz" << "0" << "1" << COPYQ_MIME_PREFIX "test-xxx" << "2",
|
||
|
data3 + ";" + data2 + ";" + data1);
|
||
|
|
||
|
// Remove
|
||
|
dir1.remove("test2.yyy");
|
||
|
|
||
|
WAIT_ON_OUTPUT(args << "size", "2\n");
|
||
|
RUN(args << "read" << COPYQ_MIME_PREFIX "test-zzz" << "0" << COPYQ_MIME_PREFIX "test-xxx" << "1",
|
||
|
data3 + ";" + data1);
|
||
|
|
||
|
// Modify file
|
||
|
const QByteArray data4 = " with update!";
|
||
|
FilePtr file = dir1.file("test1.xxx");
|
||
|
QVERIFY(file->open(QIODevice::Append));
|
||
|
file->write(data4);
|
||
|
file->close();
|
||
|
|
||
|
WAIT_ON_OUTPUT(
|
||
|
Args(args) << "read" << COPYQ_MIME_PREFIX "test-zzz" << "0" << COPYQ_MIME_PREFIX "test-xxx" << "1",
|
||
|
data3 + ";" + data1 + data4);
|
||
|
RUN(args << "size", "2\n");
|
||
|
|
||
|
// Create item with custom data
|
||
|
const QByteArray data5 = "New item data!";
|
||
|
RUN(args << "write" << COPYQ_MIME_PREFIX "test-zzz" << data5, "");
|
||
|
|
||
|
RUN(args << "size", "3\n");
|
||
|
|
||
|
const QString fileData = QString(fileNameForId(0)).replace("txt", "zzz");
|
||
|
|
||
|
// Check data
|
||
|
const QByteArray data6 = " And another data!";
|
||
|
file = dir1.file(fileData);
|
||
|
QVERIFY(file->exists());
|
||
|
QVERIFY(file->open(QIODevice::ReadWrite));
|
||
|
QCOMPARE(file->readAll().data(), data5.data());
|
||
|
|
||
|
// Modify data
|
||
|
file->write(data6);
|
||
|
file->close();
|
||
|
|
||
|
WAIT_ON_OUTPUT(
|
||
|
Args(args) << "read" << COPYQ_MIME_PREFIX "test-zzz" << "0" << "1" << COPYQ_MIME_PREFIX "test-xxx" << "2",
|
||
|
data5 + data6 + ";" + data3 + ";" + data1 + data4);
|
||
|
RUN(args << "size", "3\n");
|
||
|
}
|