Refactor Database and Database widgets (#2491)

The Database, DatabaseWidget, and DatabaseTabWidget classes share many responsibilities in inconsistent ways resulting in impenetrable and unmaintainable code and a diverse set of bugs and architecture restrictions. This patch reworks the architecture, responsibilities of, and dependencies between these classes.

The core changes are:

* Move loading and saving logic from widgets into the Database class
* Get rid of the DatabaseManagerStruct and move all the information contained in it into the Database
* Let database objects keep track of modifications and dirty/clean state instead of handing this to external widgets
* Move GUI interactions for loading and saving from the DatabaseTabWidget into the DatabaseWidget (resolves #2494 as a side-effect)
* Heavily clean up DatabaseTabWidget and degrade it to a slightly glorified QTabWidget
* Use QSharedPointers for all Database objects
* Remove the modifiedImmediate signal and replace it with a markAsModified() method
* Implement proper tabName() method instead of reading back titles from GUI widgets (resolves #1389 and its duplicates #2146 #855)
* Fix unwanted AES-KDF downgrade if database uses Argon2 and has CustomData
* Improve code

This patch is also the first major step towards solving issues #476 and #2322.
This commit is contained in:
Janek Bevendorff
2018-11-22 11:47:31 +01:00
committed by GitHub
parent 917c4cc18b
commit d612cad09a
115 changed files with 2116 additions and 2165 deletions

View File

@@ -57,7 +57,7 @@ void TestAutoType::init()
config()->set("AutoTypeEntryTitleMatch", false);
m_test->clearActions();
m_db = new Database();
m_db = QSharedPointer<Database>::create();
m_dbList.clear();
m_dbList.append(m_db);
m_group = new Group();
@@ -126,7 +126,6 @@ void TestAutoType::init()
void TestAutoType::cleanup()
{
delete m_db;
}
void TestAutoType::testInternal()

View File

@@ -20,6 +20,7 @@
#define KEEPASSX_TESTAUTOTYPE_H
#include <QObject>
#include <QSharedPointer>
class AutoType;
class AutoTypePlatformInterface;
@@ -53,8 +54,8 @@ private:
AutoTypePlatformInterface* m_platform;
AutoTypeTestInterface* m_test;
AutoType* m_autoType;
Database* m_db;
QList<Database*> m_dbList;
QSharedPointer<Database> m_db;
QList<QSharedPointer<Database>> m_dbList;
Group* m_group;
Entry* m_entry1;
Entry* m_entry2;

View File

@@ -671,7 +671,8 @@ void TestCli::testMerge()
QFile readBack(targetFile1.fileName());
readBack.open(QIODevice::ReadOnly);
QScopedPointer<Database> mergedDb(reader.readDatabase(&readBack, oldKey));
auto mergedDb = QSharedPointer<Database>::create();
reader.readDatabase(&readBack, oldKey, mergedDb.data());
readBack.close();
QVERIFY(mergedDb);
auto* entry1 = mergedDb->rootGroup()->findEntryByPath("/Internet/Some Website");
@@ -691,7 +692,8 @@ void TestCli::testMerge()
readBack.setFileName(targetFile2.fileName());
readBack.open(QIODevice::ReadOnly);
mergedDb.reset(reader.readDatabase(&readBack, key));
mergedDb = QSharedPointer<Database>::create();
reader.readDatabase(&readBack, key, mergedDb.data());
readBack.close();
QVERIFY(mergedDb);
entry1 = mergedDb->rootGroup()->findEntryByPath("/Internet/Some Website");
@@ -740,7 +742,8 @@ void TestCli::testRemove()
key->addKey(QSharedPointer<PasswordKey>::create("a"));
QFile readBack(m_dbFile->fileName());
readBack.open(QIODevice::ReadOnly);
QScopedPointer<Database> readBackDb(reader.readDatabase(&readBack, key));
auto readBackDb = QSharedPointer<Database>::create();
reader.readDatabase(&readBack, key, readBackDb.data());
readBack.close();
QVERIFY(readBackDb);
QVERIFY(!readBackDb->rootGroup()->findEntryByPath("/Sample Entry"));
@@ -757,7 +760,8 @@ void TestCli::testRemove()
readBack.setFileName(fileCopy.fileName());
readBack.open(QIODevice::ReadOnly);
readBackDb.reset(reader.readDatabase(&readBack, key));
readBackDb = QSharedPointer<Database>::create();
reader.readDatabase(&readBack, key, readBackDb.data());
readBack.close();
QVERIFY(readBackDb);
QVERIFY(!readBackDb->rootGroup()->findEntryByPath("/Sample Entry"));

View File

@@ -31,8 +31,8 @@ const QString TestCsvExporter::ExpectedHeaderLine =
void TestCsvExporter::init()
{
m_db = new Database();
m_csvExporter = new CsvExporter();
m_db = QSharedPointer<Database>::create();
m_csvExporter = QSharedPointer<CsvExporter>::create();
}
void TestCsvExporter::initTestCase()
@@ -42,17 +42,15 @@ void TestCsvExporter::initTestCase()
void TestCsvExporter::cleanup()
{
delete m_db;
delete m_csvExporter;
}
void TestCsvExporter::testExport()
{
Group* groupRoot = m_db->rootGroup();
Group* group = new Group();
auto* group = new Group();
group->setName("Test Group Name");
group->setParent(groupRoot);
Entry* entry = new Entry();
auto* entry = new Entry();
entry->setGroup(group);
entry->setTitle("Test Entry Title");
entry->setUsername("Test Username");
@@ -65,7 +63,7 @@ void TestCsvExporter::testExport()
m_csvExporter->exportDatabase(&buffer, m_db);
QString expectedResult =
QString().append(ExpectedHeaderLine).append("\"Test Group Name\",\"Test Entry Title\",\"Test Username\",\"Test "
QString().append(ExpectedHeaderLine).append("\"Root/Test Group Name\",\"Test Entry Title\",\"Test Username\",\"Test "
"Password\",\"http://test.url\",\"Test Notes\"\n");
QCOMPARE(QString::fromUtf8(buffer.buffer().constData()), expectedResult);
@@ -83,13 +81,13 @@ void TestCsvExporter::testEmptyDatabase()
void TestCsvExporter::testNestedGroups()
{
Group* groupRoot = m_db->rootGroup();
Group* group = new Group();
auto* group = new Group();
group->setName("Test Group Name");
group->setParent(groupRoot);
Group* childGroup = new Group();
auto* childGroup = new Group();
childGroup->setName("Test Sub Group Name");
childGroup->setParent(group);
Entry* entry = new Entry();
auto* entry = new Entry();
entry->setGroup(childGroup);
entry->setTitle("Test Entry Title");
@@ -100,5 +98,5 @@ void TestCsvExporter::testNestedGroups()
QCOMPARE(QString::fromUtf8(buffer.buffer().constData()),
QString()
.append(ExpectedHeaderLine)
.append("\"Test Group Name/Test Sub Group Name\",\"Test Entry Title\",\"\",\"\",\"\",\"\"\n"));
.append("\"Root/Test Group Name/Test Sub Group Name\",\"Test Entry Title\",\"\",\"\",\"\",\"\"\n"));
}

View File

@@ -20,6 +20,7 @@
#define KEEPASSX_TESTCSVEXPORTER_H
#include <QObject>
#include <QSharedPointer>
class Database;
class CsvExporter;
@@ -40,8 +41,8 @@ private slots:
void testNestedGroups();
private:
Database* m_db;
CsvExporter* m_csvExporter;
QSharedPointer<Database> m_db;
QSharedPointer<CsvExporter> m_csvExporter;
};
#endif // KEEPASSX_TESTCSVEXPORTER_H

View File

@@ -40,14 +40,18 @@ void TestDatabase::testEmptyRecycleBinOnDisabled()
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/RecycleBinDisabled.kdbx");
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("123"));
QScopedPointer<Database> db(Database::openDatabaseFile(filename, key));
QVERIFY(db);
auto db = QSharedPointer<Database>::create();
QVERIFY(db->open(filename, key, nullptr, false));
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
// Explicitly mark DB as read-write in case it was opened from a read-only drive.
// Prevents assertion failures on CI systems when the data dir is not writable
db->setReadOnly(false);
QSignalSpy spyModified(db.data(), SIGNAL(databaseModified()));
db->emptyRecycleBin();
// The database must be unmodified in this test after emptying the recycle bin.
QCOMPARE(spyModified.count(), 0);
QTRY_COMPARE(spyModified.count(), 0);
}
void TestDatabase::testEmptyRecycleBinOnNotCreated()
@@ -55,14 +59,15 @@ void TestDatabase::testEmptyRecycleBinOnNotCreated()
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/RecycleBinNotYetCreated.kdbx");
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("123"));
QScopedPointer<Database> db(Database::openDatabaseFile(filename, key));
QVERIFY(db);
auto db = QSharedPointer<Database>::create();
QVERIFY(db->open(filename, key, nullptr, false));
db->setReadOnly(false);
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
QSignalSpy spyModified(db.data(), SIGNAL(databaseModified()));
db->emptyRecycleBin();
// The database must be unmodified in this test after emptying the recycle bin.
QCOMPARE(spyModified.count(), 0);
QTRY_COMPARE(spyModified.count(), 0);
}
void TestDatabase::testEmptyRecycleBinOnEmpty()
@@ -70,14 +75,15 @@ void TestDatabase::testEmptyRecycleBinOnEmpty()
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/RecycleBinEmpty.kdbx");
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("123"));
QScopedPointer<Database> db(Database::openDatabaseFile(filename, key));
QVERIFY(db);
auto db = QSharedPointer<Database>::create();
QVERIFY(db->open(filename, key, nullptr, false));
db->setReadOnly(false);
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
QSignalSpy spyModified(db.data(), SIGNAL(databaseModified()));
db->emptyRecycleBin();
// The database must be unmodified in this test after emptying the recycle bin.
QCOMPARE(spyModified.count(), 0);
QTRY_COMPARE(spyModified.count(), 0);
}
void TestDatabase::testEmptyRecycleBinWithHierarchicalData()
@@ -85,8 +91,9 @@ void TestDatabase::testEmptyRecycleBinWithHierarchicalData()
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/RecycleBinWithData.kdbx");
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("123"));
QScopedPointer<Database> db(Database::openDatabaseFile(filename, key));
QVERIFY(db);
auto db = QSharedPointer<Database>::create();
QVERIFY(db->open(filename, key, nullptr, false));
db->setReadOnly(false);
QFile originalFile(filename);
qint64 initialSize = originalFile.size();
@@ -97,6 +104,8 @@ void TestDatabase::testEmptyRecycleBinWithHierarchicalData()
QVERIFY(db->metadata()->recycleBin()->children().empty());
QTemporaryFile afterCleanup;
afterCleanup.open();
KeePass2Writer writer;
writer.writeDatabase(&afterCleanup, db.data());
QVERIFY(afterCleanup.size() < initialSize);

View File

@@ -30,7 +30,7 @@ void TestDeletedObjects::initTestCase()
QVERIFY(Crypto::init());
}
void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize)
void TestDeletedObjects::createAndDelete(QSharedPointer<Database> db, int delObjectsSize)
{
QCOMPARE(db->deletedObjects().size(), delObjectsSize);
Group* root = db->rootGroup();
@@ -89,32 +89,27 @@ void TestDeletedObjects::testDeletedObjectsFromFile()
KdbxXmlReader reader(KeePass2::FILE_VERSION_3_1);
reader.setStrictMode(true);
QString xmlFile = QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.xml");
Database* db = reader.readDatabase(xmlFile);
auto db = reader.readDatabase(xmlFile);
createAndDelete(db, 2);
delete db;
}
void TestDeletedObjects::testDeletedObjectsFromNewDb()
{
Database* db = new Database();
auto db = QSharedPointer<Database>::create();
createAndDelete(db, 0);
delete db;
}
void TestDeletedObjects::testDatabaseChange()
{
Database* db = new Database();
auto db = QSharedPointer<Database>::create();
Group* root = db->rootGroup();
int delObjectsSize = 0;
Database* db2 = new Database();
auto db2 = QSharedPointer<Database>::create();
Group* root2 = db2->rootGroup();
int delObjectsSize2 = 0;
Entry* e = new Entry();
auto* e = new Entry();
e->setGroup(root);
QCOMPARE(db->deletedObjects().size(), delObjectsSize);
@@ -130,11 +125,11 @@ void TestDeletedObjects::testDatabaseChange()
QCOMPARE(db->deletedObjects().size(), delObjectsSize);
QCOMPARE(db2->deletedObjects().size(), ++delObjectsSize2);
Group* g1 = new Group();
auto* g1 = new Group();
g1->setParent(root);
QUuid g1Uuid = QUuid::createUuid();
g1->setUuid(g1Uuid);
Entry* e1 = new Entry();
auto* e1 = new Entry();
e1->setGroup(g1);
QUuid e1Uuid = QUuid::createUuid();
e1->setUuid(e1Uuid);
@@ -146,8 +141,8 @@ void TestDeletedObjects::testDatabaseChange()
QCOMPARE(db->deletedObjects().at(delObjectsSize - 2).uuid, e1Uuid);
QCOMPARE(db->deletedObjects().at(delObjectsSize - 1).uuid, g1Uuid);
Group* group = new Group();
Entry* entry = new Entry();
auto* group = new Group();
auto* entry = new Entry();
entry->setGroup(group);
entry->setGroup(root);
@@ -155,6 +150,4 @@ void TestDeletedObjects::testDatabaseChange()
QCOMPARE(db2->deletedObjects().size(), delObjectsSize2);
delete group;
delete db;
delete db2;
}

View File

@@ -27,7 +27,7 @@ class TestDeletedObjects : public QObject
Q_OBJECT
private:
void createAndDelete(Database* db, int delObjectsSize);
void createAndDelete(QSharedPointer<Database> db, int delObjectsSize);
private slots:
void initTestCase();

View File

@@ -37,7 +37,7 @@ void TestKdbx2::initTestCase()
/**
* Helper method for verifying contents of the sample KDBX 2 file.
*/
void TestKdbx2::verifyKdbx2Db(Database* db)
void TestKdbx2::verifyKdbx2Db(QSharedPointer<Database> db)
{
QVERIFY(db);
QCOMPARE(db->rootGroup()->name(), QString("Format200"));
@@ -67,12 +67,13 @@ void TestKdbx2::testFormat200()
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/Format200.kdbx");
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("a"));
auto db = QSharedPointer<Database>::create();
KeePass2Reader reader;
QScopedPointer<Database> db(reader.readDatabase(filename, key));
QVERIFY(reader.readDatabase(filename, key, db.data()));
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_2 & KeePass2::FILE_VERSION_CRITICAL_MASK);
QVERIFY2(!reader.hasError(), reader.errorString().toStdString().c_str());
verifyKdbx2Db(db.data());
verifyKdbx2Db(db);
}
void TestKdbx2::testFormat200Upgrade()
@@ -80,8 +81,9 @@ void TestKdbx2::testFormat200Upgrade()
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/Format200.kdbx");
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("a"));
auto db = QSharedPointer<Database>::create();
KeePass2Reader reader;
QScopedPointer<Database> db(reader.readDatabase(filename, key));
reader.readDatabase(filename, key, db.data());
QVERIFY2(!reader.hasError(), reader.errorString().toStdString().c_str());
QVERIFY(!db.isNull());
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_2 & KeePass2::FILE_VERSION_CRITICAL_MASK);
@@ -92,20 +94,21 @@ void TestKdbx2::testFormat200Upgrade()
// write KDBX 3 to upgrade it
KeePass2Writer writer;
writer.writeDatabase(&buffer, db.data());
QVERIFY(writer.writeDatabase(&buffer, db.data()));
if (writer.hasError()) {
QFAIL(qPrintable(QString("Error while writing database: %1").arg(writer.errorString())));
}
// read buffer back
buffer.seek(0);
QScopedPointer<Database> targetDb(reader.readDatabase(&buffer, key));
auto targetDb = QSharedPointer<Database>::create();
QVERIFY(reader.readDatabase(&buffer, key, targetDb.data()));
if (reader.hasError()) {
QFAIL(qPrintable(QString("Error while reading database: %1").arg(reader.errorString())));
}
// database should now be upgraded to KDBX 3 without data loss
verifyKdbx2Db(targetDb.data());
verifyKdbx2Db(targetDb);
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_3_1 & KeePass2::FILE_VERSION_CRITICAL_MASK);
QCOMPARE(targetDb->kdf()->uuid(), KeePass2::KDF_AES_KDBX3);
}

View File

@@ -32,7 +32,7 @@ private slots:
void testFormat200Upgrade();
private:
void verifyKdbx2Db(Database* db);
void verifyKdbx2Db(QSharedPointer<Database> db);
};
#endif // KEEPASSXC_TEST_KDBX2_H

View File

@@ -33,7 +33,7 @@ void TestKdbx3::initTestCaseImpl()
{
}
Database* TestKdbx3::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)
QSharedPointer<Database> TestKdbx3::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)
{
KdbxXmlReader reader(KeePass2::FILE_VERSION_3_1);
reader.setStrictMode(strictMode);
@@ -43,7 +43,7 @@ Database* TestKdbx3::readXml(const QString& path, bool strictMode, bool& hasErro
return db;
}
Database* TestKdbx3::readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString)
QSharedPointer<Database> TestKdbx3::readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString)
{
KdbxXmlReader reader(KeePass2::FILE_VERSION_3_1);
reader.setStrictMode(strictMode);
@@ -63,12 +63,12 @@ void TestKdbx3::writeXml(QBuffer* buf, Database* db, bool& hasError, QString& er
void TestKdbx3::readKdbx(QIODevice* device,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString)
{
KeePass2Reader reader;
db.reset(reader.readDatabase(device, key));
reader.readDatabase(device, key, db.data());
hasError = reader.hasError();
if (hasError) {
errorString = reader.errorString();
@@ -78,12 +78,12 @@ void TestKdbx3::readKdbx(QIODevice* device,
void TestKdbx3::readKdbx(const QString& path,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString)
{
KeePass2Reader reader;
db.reset(reader.readDatabase(path, key));
reader.readDatabase(path, key, db.data());
hasError = reader.hasError();
if (hasError) {
errorString = reader.errorString();
@@ -108,7 +108,8 @@ void TestKdbx3::testFormat300()
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("a"));
KeePass2Reader reader;
QScopedPointer<Database> db(reader.readDatabase(filename, key));
auto db = QSharedPointer<Database>::create();
QVERIFY(reader.readDatabase(filename, key, db.data()));
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_3);
QVERIFY(db.data());
QVERIFY(!reader.hasError());
@@ -123,11 +124,12 @@ void TestKdbx3::testNonAscii()
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create(QString::fromUtf8("\xce\x94\xc3\xb6\xd8\xb6")));
KeePass2Reader reader;
QScopedPointer<Database> db(reader.readDatabase(filename, key));
auto db = QSharedPointer<Database>::create();
QVERIFY(db->open(filename, key, nullptr, false));
QVERIFY(db.data());
QVERIFY(!reader.hasError());
QCOMPARE(db->metadata()->name(), QString("NonAsciiTest"));
QCOMPARE(db->compressionAlgo(), Database::CompressionNone);
QCOMPARE(db->compressionAlgorithm(), Database::CompressionNone);
}
void TestKdbx3::testCompressed()
@@ -136,11 +138,12 @@ void TestKdbx3::testCompressed()
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create(""));
KeePass2Reader reader;
QScopedPointer<Database> db(reader.readDatabase(filename, key));
auto db = QSharedPointer<Database>::create();
QVERIFY(db->open(filename, key, nullptr, false));
QVERIFY(db.data());
QVERIFY(!reader.hasError());
QCOMPARE(db->metadata()->name(), QString("Compressed"));
QCOMPARE(db->compressionAlgo(), Database::CompressionGZip);
QCOMPARE(db->compressionAlgorithm(), Database::CompressionGZip);
}
void TestKdbx3::testProtectedStrings()
@@ -149,7 +152,8 @@ void TestKdbx3::testProtectedStrings()
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("masterpw"));
KeePass2Reader reader;
QScopedPointer<Database> db(reader.readDatabase(filename, key));
auto db = QSharedPointer<Database>::create();
QVERIFY(db->open(filename, key, nullptr, false));
QVERIFY(db.data());
QVERIFY(!reader.hasError());
QCOMPARE(db->metadata()->name(), QString("Protected Strings Test"));
@@ -175,8 +179,6 @@ void TestKdbx3::testBrokenHeaderHash()
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/BrokenHeaderHash.kdbx");
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create(""));
KeePass2Reader reader;
QScopedPointer<Database> db(reader.readDatabase(filename, key));
QVERIFY(!db.data());
QVERIFY(reader.hasError());
auto db = QSharedPointer<Database>::create();
QVERIFY(!db->open(filename, key, nullptr, false));
}

View File

@@ -34,18 +34,18 @@ private slots:
protected:
void initTestCaseImpl() override;
Database* readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString) override;
Database* readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) override;
QSharedPointer<Database> readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString) override;
QSharedPointer<Database> readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) override;
void writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString) override;
void readKdbx(QIODevice* device,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString) override;
void readKdbx(const QString& path,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString) override;
void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) override;

View File

@@ -37,7 +37,7 @@ void TestKdbx4::initTestCaseImpl()
m_kdbxSourceDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)));
}
Database* TestKdbx4::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)
QSharedPointer<Database> TestKdbx4::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)
{
KdbxXmlReader reader(KeePass2::FILE_VERSION_4);
reader.setStrictMode(strictMode);
@@ -47,7 +47,7 @@ Database* TestKdbx4::readXml(const QString& path, bool strictMode, bool& hasErro
return db;
}
Database* TestKdbx4::readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString)
QSharedPointer<Database> TestKdbx4::readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString)
{
KdbxXmlReader reader(KeePass2::FILE_VERSION_4);
reader.setStrictMode(strictMode);
@@ -67,12 +67,12 @@ void TestKdbx4::writeXml(QBuffer* buf, Database* db, bool& hasError, QString& er
void TestKdbx4::readKdbx(QIODevice* device,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString)
{
KeePass2Reader reader;
db.reset(reader.readDatabase(device, key));
reader.readDatabase(device, key, db.data());
hasError = reader.hasError();
if (hasError) {
errorString = reader.errorString();
@@ -82,12 +82,12 @@ void TestKdbx4::readKdbx(QIODevice* device,
void TestKdbx4::readKdbx(const QString& path,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString)
{
KeePass2Reader reader;
db.reset(reader.readDatabase(path, key));
reader.readDatabase(path, key, db.data());
hasError = reader.hasError();
if (hasError) {
errorString = reader.errorString();
@@ -116,7 +116,8 @@ void TestKdbx4::testFormat400()
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("t"));
KeePass2Reader reader;
QScopedPointer<Database> db(reader.readDatabase(filename, key));
auto db = QSharedPointer<Database>::create();
reader.readDatabase(filename, key, db.data());
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_4);
QVERIFY(db.data());
QVERIFY(!reader.hasError());
@@ -174,7 +175,8 @@ void TestKdbx4::testFormat400Upgrade()
// read buffer back
buffer.seek(0);
KeePass2Reader reader;
QScopedPointer<Database> targetDb(reader.readDatabase(&buffer, key));
auto targetDb = QSharedPointer<Database>::create();
reader.readDatabase(&buffer, key, targetDb.data());
if (reader.hasError()) {
QFAIL(qPrintable(QString("Error while reading database: %1").arg(reader.errorString())));
}
@@ -292,14 +294,15 @@ void TestKdbx4::testUpgradeMasterKeyIntegrity()
// paranoid check that we cannot decrypt the database without a key
buffer.seek(0);
KeePass2Reader reader;
QScopedPointer<Database> db2;
db2.reset(reader.readDatabase(&buffer, QSharedPointer<CompositeKey>::create()));
auto db2 = QSharedPointer<Database>::create();
reader.readDatabase(&buffer, QSharedPointer<CompositeKey>::create(), db2.data());
QVERIFY(reader.hasError());
// check that we can read back the database with the original composite key,
// i.e., no components have been lost on the way
buffer.seek(0);
db2.reset(reader.readDatabase(&buffer, compositeKey));
db2 = QSharedPointer<Database>::create();
reader.readDatabase(&buffer, compositeKey, db2.data());
if (reader.hasError()) {
QFAIL(qPrintable(reader.errorString()));
}
@@ -396,7 +399,8 @@ void TestKdbx4::testCustomData()
// read buffer back
buffer.seek(0);
KeePass2Reader reader;
QSharedPointer<Database> newDb(reader.readDatabase(&buffer, QSharedPointer<CompositeKey>::create()));
auto newDb = QSharedPointer<Database>::create();
reader.readDatabase(&buffer, QSharedPointer<CompositeKey>::create(), newDb.data());
// test all custom data are read back successfully from KDBX
QCOMPARE(newDb->publicCustomData(), publicCustomData);

View File

@@ -35,18 +35,18 @@ private slots:
protected:
void initTestCaseImpl() override;
Database* readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString) override;
Database* readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) override;
QSharedPointer<Database> readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString) override;
QSharedPointer<Database> readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) override;
void writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString) override;
void readKdbx(const QString& path,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString) override;
void readKdbx(QIODevice* device,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString) override;
void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) override;

View File

@@ -177,15 +177,13 @@ void TestKeePass1Reader::testFileKey()
QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
QString keyFilename = QString("%1/%2.key").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
Database* db = reader.readDatabase(dbFilename, QString(), keyFilename);
auto db = reader.readDatabase(dbFilename, QString(), keyFilename);
QVERIFY(db);
QVERIFY(!reader.hasError());
QCOMPARE(db->rootGroup()->children().size(), 1);
QCOMPARE(db->rootGroup()->children().at(0)->name(), name);
reopenDatabase(db, QString(), keyFilename);
delete db;
}
void TestKeePass1Reader::testFileKey_data()
@@ -205,15 +203,13 @@ void TestKeePass1Reader::testCompositeKey()
QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
QString keyFilename = QString("%1/FileKeyHex.key").arg(QString(KEEPASSX_TEST_DATA_DIR));
Database* db = reader.readDatabase(dbFilename, "mypassword", keyFilename);
auto db = reader.readDatabase(dbFilename, "mypassword", keyFilename);
QVERIFY(db);
QVERIFY(!reader.hasError());
QCOMPARE(db->rootGroup()->children().size(), 1);
QCOMPARE(db->rootGroup()->children().at(0)->name(), name);
reopenDatabase(db, "mypassword", keyFilename);
delete db;
}
void TestKeePass1Reader::testTwofish()
@@ -224,13 +220,11 @@ void TestKeePass1Reader::testTwofish()
QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
Database* db = reader.readDatabase(dbFilename, "masterpw", 0);
auto db = reader.readDatabase(dbFilename, "masterpw", 0);
QVERIFY(db);
QVERIFY(!reader.hasError());
QCOMPARE(db->rootGroup()->children().size(), 1);
QCOMPARE(db->rootGroup()->children().at(0)->name(), name);
delete db;
}
void TestKeePass1Reader::testCP1252Password()
@@ -242,18 +236,15 @@ void TestKeePass1Reader::testCP1252Password()
QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
QString password = QString::fromUtf8("\xe2\x80\x9e\x70\x61\x73\x73\x77\x6f\x72\x64\xe2\x80\x9d");
Database* db = reader.readDatabase(dbFilename, password, 0);
auto db = reader.readDatabase(dbFilename, password, 0);
QVERIFY(db);
QVERIFY(!reader.hasError());
QCOMPARE(db->rootGroup()->children().size(), 1);
QCOMPARE(db->rootGroup()->children().at(0)->name(), name);
delete db;
}
void TestKeePass1Reader::cleanupTestCase()
{
delete m_db;
}
QDateTime TestKeePass1Reader::genDT(int year, int month, int day, int hour, int min)
@@ -263,13 +254,15 @@ QDateTime TestKeePass1Reader::genDT(int year, int month, int day, int hour, int
return QDateTime(date, time, Qt::UTC);
}
void TestKeePass1Reader::reopenDatabase(Database* db, const QString& password, const QString& keyfileName)
void TestKeePass1Reader::reopenDatabase(QSharedPointer<Database> db,
const QString& password,
const QString& keyfileName)
{
QBuffer buffer;
buffer.open(QIODevice::ReadWrite);
KeePass2Writer writer;
writer.writeDatabase(&buffer, db);
writer.writeDatabase(&buffer, db.data());
QVERIFY(!writer.hasError());
QVERIFY(buffer.seek(0));
@@ -284,7 +277,7 @@ void TestKeePass1Reader::reopenDatabase(Database* db, const QString& password, c
}
KeePass2Reader reader;
QScopedPointer<Database> newDb(reader.readDatabase(&buffer, key));
QVERIFY(newDb);
auto newDb = QSharedPointer<Database>::create();
QVERIFY(reader.readDatabase(&buffer, key, newDb.data()));
QVERIFY(!reader.hasError());
}

View File

@@ -20,6 +20,7 @@
#include <QDateTime>
#include <QObject>
#include <QSharedPointer>
class Database;
@@ -43,9 +44,9 @@ private slots:
private:
static QDateTime genDT(int year, int month, int day, int hour, int min);
static void reopenDatabase(Database* db, const QString& password, const QString& keyfileName);
static void reopenDatabase(QSharedPointer<Database> db, const QString& password, const QString& keyfileName);
Database* m_db;
QSharedPointer<Database> m_db;
};
#endif // KEEPASSX_TESTKEEPASS1READER_H

View File

@@ -34,7 +34,7 @@ void TestKeePass2Format::initTestCase()
// read raw XML database
bool hasError;
QString errorString;
m_xmlDb.reset(readXml(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.xml"), true, hasError, errorString));
m_xmlDb = readXml(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.xml"), true, hasError, errorString);
if (hasError) {
QFAIL(qPrintable(QString("Error while reading XML: ").append(errorString)));
}
@@ -44,7 +44,7 @@ void TestKeePass2Format::initTestCase()
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("test"));
m_kdbxSourceDb.reset(new Database());
m_kdbxSourceDb = QSharedPointer<Database>::create();
m_kdbxSourceDb->setKey(key);
m_kdbxSourceDb->metadata()->setName("TESTDB");
Group* group = m_kdbxSourceDb->rootGroup();
@@ -351,7 +351,7 @@ void TestKeePass2Format::testXmlBroken()
QVERIFY(QFile::exists(xmlFile));
bool hasError;
QString errorString;
QScopedPointer<Database> db(readXml(xmlFile, strictMode, hasError, errorString));
auto db = readXml(xmlFile, strictMode, hasError, errorString);
if (hasError) {
qWarning("Reader error: %s", qPrintable(errorString));
}
@@ -392,7 +392,7 @@ void TestKeePass2Format::testXmlEmptyUuids()
QVERIFY(QFile::exists(xmlFile));
bool hasError;
QString errorString;
QScopedPointer<Database> dbp(readXml(xmlFile, true, hasError, errorString));
auto db = readXml(xmlFile, true, hasError, errorString);
if (hasError) {
qWarning("Reader error: %s", qPrintable(errorString));
}
@@ -446,7 +446,7 @@ void TestKeePass2Format::testXmlInvalidXmlChars()
QVERIFY(!hasError);
buffer.seek(0);
QScopedPointer<Database> dbRead(readXml(&buffer, true, hasError, errorString));
auto dbRead = readXml(&buffer, true, hasError, errorString);
if (hasError) {
qWarning("Database read error: %s", qPrintable(errorString));
}
@@ -474,7 +474,7 @@ void TestKeePass2Format::testXmlRepairUuidHistoryItem()
QVERIFY(QFile::exists(xmlFile));
bool hasError;
QString errorString;
QScopedPointer<Database> db(readXml(xmlFile, false, hasError, errorString));
auto db = readXml(xmlFile, false, hasError, errorString);
if (hasError) {
qWarning("Database read error: %s", qPrintable(errorString));
}
@@ -503,6 +503,7 @@ void TestKeePass2Format::testReadBackTargetDb()
QString errorString;
m_kdbxTargetBuffer.seek(0);
m_kdbxTargetDb = QSharedPointer<Database>::create();
readKdbx(&m_kdbxTargetBuffer, key, m_kdbxTargetDb, hasError, errorString);
if (hasError) {
QFAIL(qPrintable(QString("Error while reading database: ").append(errorString)));
@@ -548,7 +549,7 @@ void TestKeePass2Format::testKdbxDeviceFailure()
QScopedPointer<Database> db(new Database());
db->setKey(key);
// Disable compression so we write a predictable number of bytes.
db->setCompressionAlgo(Database::CompressionNone);
db->setCompressionAlgorithm(Database::CompressionNone);
auto entry = new Entry();
entry->setParent(db->rootGroup());
@@ -569,7 +570,7 @@ void TestKeePass2Format::testKdbxDeviceFailure()
*/
void TestKeePass2Format::testDuplicateAttachments()
{
QScopedPointer<Database> db(new Database());
auto db = QSharedPointer<Database>::create();
db->setKey(QSharedPointer<CompositeKey>::create());
const QByteArray attachment1("abc");

View File

@@ -21,7 +21,7 @@
#include <QBuffer>
#include <QDateTime>
#include <QObject>
#include <QScopedPointer>
#include <QSharedPointer>
#include "core/Database.h"
@@ -67,25 +67,25 @@ private slots:
protected:
virtual void initTestCaseImpl() = 0;
virtual Database* readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString) = 0;
virtual Database* readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) = 0;
virtual QSharedPointer<Database> readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString) = 0;
virtual QSharedPointer<Database> readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) = 0;
virtual void writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString) = 0;
virtual void readKdbx(QIODevice* device,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString) = 0;
virtual void readKdbx(const QString& path,
QSharedPointer<const CompositeKey> key,
QScopedPointer<Database>& db,
QSharedPointer<Database> db,
bool& hasError,
QString& errorString) = 0;
virtual void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) = 0;
QScopedPointer<Database> m_xmlDb;
QScopedPointer<Database> m_kdbxSourceDb;
QScopedPointer<Database> m_kdbxTargetDb;
QSharedPointer<Database> m_xmlDb;
QSharedPointer<Database> m_kdbxSourceDb;
QSharedPointer<Database> m_kdbxTargetDb;
private:
QBuffer m_kdbxTargetBuffer;

View File

@@ -87,8 +87,8 @@ void TestKeys::testFileKey()
compositeKey->addKey(fileKey);
QScopedPointer<Database> db(reader.readDatabase(dbFilename, compositeKey));
QVERIFY(db);
auto db = QSharedPointer<Database>::create();
QVERIFY(db->open(dbFilename, compositeKey, nullptr, false));
QVERIFY(!reader.hasError());
QCOMPARE(db->metadata()->name(), QString("%1 Database").arg(name));
}
@@ -152,7 +152,8 @@ void TestKeys::testCreateAndOpenFileKey()
dbBuffer.reset();
KeePass2Reader reader;
QScopedPointer<Database> dbRead(reader.readDatabase(&dbBuffer, compositeKey));
auto dbRead = QSharedPointer<Database>::create();
reader.readDatabase(&dbBuffer, compositeKey, dbRead.data());
if (reader.hasError()) {
QFAIL(reader.errorString().toUtf8().constData());
}
@@ -236,7 +237,7 @@ void TestKeys::testCompositeKeyComponents()
compositeKeyEnc->addKey(fileKeyEnc);
compositeKeyEnc->addChallengeResponseKey(challengeResponseKeyEnc);
QScopedPointer<Database> db1(new Database());
auto db1 = QSharedPointer<Database>::create();
db1->setKey(compositeKeyEnc);
KeePass2Writer writer;
@@ -245,27 +246,27 @@ void TestKeys::testCompositeKeyComponents()
QVERIFY(writer.writeDatabase(&buffer, db1.data()));
buffer.seek(0);
QScopedPointer<Database> db2;
auto db2 = QSharedPointer<Database>::create();
KeePass2Reader reader;
auto compositeKeyDec1 = QSharedPointer<CompositeKey>::create();
// try decryption and subsequently add key components until decryption is successful
db2.reset(reader.readDatabase(&buffer, compositeKeyDec1));
QVERIFY(!reader.readDatabase(&buffer, compositeKeyDec1, db2.data()));
QVERIFY(reader.hasError());
compositeKeyDec1->addKey(passwordKeyEnc);
buffer.seek(0);
db2.reset(reader.readDatabase(&buffer, compositeKeyDec1));
QVERIFY(!reader.readDatabase(&buffer, compositeKeyDec1, db2.data()));
QVERIFY(reader.hasError());
compositeKeyDec1->addKey(fileKeyEnc);
buffer.seek(0);
db2.reset(reader.readDatabase(&buffer, compositeKeyDec1));
QVERIFY(!reader.readDatabase(&buffer, compositeKeyDec1, db2.data()));
QVERIFY(reader.hasError());
compositeKeyDec1->addChallengeResponseKey(challengeResponseKeyEnc);
buffer.seek(0);
db2.reset(reader.readDatabase(&buffer, compositeKeyDec1));
QVERIFY(reader.readDatabase(&buffer, compositeKeyDec1, db2.data()));
// now we should be able to open the database
if (reader.hasError()) {
QFAIL(qPrintable(reader.errorString()));
@@ -277,7 +278,7 @@ void TestKeys::testCompositeKeyComponents()
compositeKeyDec2->addKey(fileKeyEnc);
compositeKeyDec2->addChallengeResponseKey(challengeResponseKeyEnc);
buffer.seek(0);
db2.reset(reader.readDatabase(&buffer, compositeKeyDec2));
QVERIFY(!reader.readDatabase(&buffer, compositeKeyDec2, db2.data()));
QVERIFY(reader.hasError());
auto compositeKeyDec3 = QSharedPointer<CompositeKey>::create();
@@ -290,7 +291,7 @@ void TestKeys::testCompositeKeyComponents()
compositeKeyDec3->addKey(fileKeyWrong);
compositeKeyDec3->addChallengeResponseKey(challengeResponseKeyEnc);
buffer.seek(0);
db2.reset(reader.readDatabase(&buffer, compositeKeyDec3));
QVERIFY(!reader.readDatabase(&buffer, compositeKeyDec3, db2.data()));
QVERIFY(reader.hasError());
auto compositeKeyDec4 = QSharedPointer<CompositeKey>::create();
@@ -298,6 +299,6 @@ void TestKeys::testCompositeKeyComponents()
compositeKeyDec4->addKey(fileKeyEnc);
compositeKeyDec4->addChallengeResponseKey(QSharedPointer<MockChallengeResponseKey>::create(QByteArray(16, 0x20)));
buffer.seek(0);
db2.reset(reader.readDatabase(&buffer, compositeKeyDec4));
QVERIFY(!reader.readDatabase(&buffer, compositeKeyDec4, db2.data()));
QVERIFY(reader.hasError());
}

View File

@@ -1363,10 +1363,10 @@ void TestMerge::testMergeNotModified()
QScopedPointer<Database> dbSource(
createTestDatabaseStructureClone(dbDestination.data(), Entry::CloneNoFlags, Group::CloneIncludeEntries));
QSignalSpy modifiedSignalSpy(dbDestination.data(), SIGNAL(modified()));
QSignalSpy modifiedSignalSpy(dbDestination.data(), SIGNAL(databaseModified()));
Merger merger(dbSource.data(), dbDestination.data());
merger.merge();
QVERIFY(modifiedSignalSpy.empty());
QTRY_VERIFY(modifiedSignalSpy.empty());
}
void TestMerge::testMergeModified()
@@ -1375,7 +1375,7 @@ void TestMerge::testMergeModified()
QScopedPointer<Database> dbSource(
createTestDatabaseStructureClone(dbDestination.data(), Entry::CloneNoFlags, Group::CloneIncludeEntries));
QSignalSpy modifiedSignalSpy(dbDestination.data(), SIGNAL(modified()));
QSignalSpy modifiedSignalSpy(dbDestination.data(), SIGNAL(databaseModified()));
// Make sure the two changes have a different timestamp.
QTest::qSleep(1);
Entry* entry = dbSource->rootGroup()->findEntryByPath("entry1");
@@ -1385,7 +1385,7 @@ void TestMerge::testMergeModified()
Merger merger(dbSource.data(), dbDestination.data());
merger.merge();
QVERIFY(!modifiedSignalSpy.empty());
QTRY_VERIFY(!modifiedSignalSpy.empty());
}
Database* TestMerge::createTestDatabase()

View File

@@ -61,67 +61,83 @@ void TestModified::testSignals()
QScopedPointer<Database> db(new Database());
auto* root = db->rootGroup();
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
QSignalSpy spyModified(db.data(), SIGNAL(databaseModified()));
db->setKey(compositeKey);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
auto* group1 = new Group();
group1->setParent(root);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
auto* group2 = new Group();
group2->setParent(root);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
group2->setParent(root, 0);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
auto* entry1 = new Entry();
entry1->setGroup(group1);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
QScopedPointer<Database> db2(new Database());
auto* root2 = db2->rootGroup();
QSignalSpy spyModified2(db2.data(), SIGNAL(modifiedImmediate()));
QSignalSpy spyModified2(db2.data(), SIGNAL(databaseModified()));
group1->setParent(root2);
QCOMPARE(spyModified.count(), ++spyCount);
QCOMPARE(spyModified2.count(), ++spyCount2);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
++spyCount2;
QTRY_COMPARE(spyModified2.count(), spyCount2);
entry1->setTitle("test");
QCOMPARE(spyModified.count(), spyCount);
QCOMPARE(spyModified2.count(), ++spyCount2);
QTRY_COMPARE(spyModified.count(), spyCount);
++spyCount2;
QTRY_COMPARE(spyModified2.count(), spyCount2);
auto* entry2 = new Entry();
entry2->setGroup(group2);
QCOMPARE(spyModified.count(), ++spyCount);
QCOMPARE(spyModified2.count(), spyCount2);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified2.count(), spyCount2);
entry2->setGroup(root2);
QCOMPARE(spyModified.count(), ++spyCount);
QCOMPARE(spyModified2.count(), ++spyCount2);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
++spyCount2;
QTRY_COMPARE(spyModified2.count(), spyCount2);
entry2->setTitle("test2");
QCOMPARE(spyModified.count(), spyCount);
QCOMPARE(spyModified2.count(), ++spyCount2);
QTRY_COMPARE(spyModified.count(), spyCount);
++spyCount2;
QTRY_COMPARE(spyModified2.count(), spyCount2);
auto* group3 = new Group();
group3->setParent(root);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
auto* group4 = new Group();
group4->setParent(group3);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
delete group4;
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
delete entry2;
QCOMPARE(spyModified2.count(), ++spyCount2);
++spyCount2;
QTRY_COMPARE(spyModified2.count(), spyCount2);
QCOMPARE(spyModified.count(), spyCount);
QCOMPARE(spyModified2.count(), spyCount2);
QTRY_COMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified2.count(), spyCount2);
}
void TestModified::testGroupSets()
@@ -133,58 +149,68 @@ void TestModified::testGroupSets()
auto* group = new Group();
group->setParent(root);
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
QSignalSpy spyModified(db.data(), SIGNAL(databaseModified()));
root->setUuid(QUuid::createUuid());
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
root->setUuid(root->uuid());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
root->setName("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
root->setName(root->name());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
root->setNotes("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
root->setNotes(root->notes());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
root->setIcon(1);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
root->setIcon(root->iconNumber());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
root->setIcon(QUuid::createUuid());
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
root->setIcon(root->iconUuid());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
group->setUuid(QUuid::createUuid());
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
group->setUuid(group->uuid());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
group->setName("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
group->setName(group->name());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
group->setNotes("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
group->setNotes(group->notes());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
group->setIcon(1);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
group->setIcon(group->iconNumber());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
group->setIcon(QUuid::createUuid());
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
group->setIcon(group->iconUuid());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
}
void TestModified::testEntrySets()
@@ -198,106 +224,127 @@ void TestModified::testEntrySets()
auto* entry = new Entry();
entry->setGroup(group);
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
QSignalSpy spyModified(db.data(), SIGNAL(databaseModified()));
entry->setUuid(QUuid::createUuid());
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setUuid(entry->uuid());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setTitle("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setTitle(entry->title());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setUrl("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setUrl(entry->url());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setUsername("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setUsername(entry->username());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setPassword("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setPassword(entry->password());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setNotes("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setNotes(entry->notes());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setIcon(1);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setIcon(entry->iconNumber());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setIcon(QUuid::createUuid());
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setIcon(entry->iconUuid());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setTags("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setTags(entry->tags());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setExpires(true);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setExpires(entry->timeInfo().expires());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setExpiryTime(Clock::currentDateTimeUtc().addYears(1));
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setExpiryTime(entry->timeInfo().expiryTime());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setAutoTypeEnabled(false);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setAutoTypeEnabled(entry->autoTypeEnabled());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setAutoTypeObfuscation(1);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setAutoTypeObfuscation(entry->autoTypeObfuscation());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setDefaultAutoTypeSequence("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setDefaultAutoTypeSequence(entry->defaultAutoTypeSequence());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setForegroundColor(Qt::red);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setForegroundColor(entry->foregroundColor());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setBackgroundColor(Qt::red);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setBackgroundColor(entry->backgroundColor());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setOverrideUrl("test");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->setOverrideUrl(entry->overrideUrl());
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->attributes()->set("test key", "test value", false);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->attributes()->set("test key", entry->attributes()->value("test key"), false);
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->attributes()->set("test key", entry->attributes()->value("test key"), true);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->attributes()->set("test key", "new test value", true);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->attributes()->set("test key2", "test value2", true);
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->attributes()->set("test key2", entry->attributes()->value("test key2"), true);
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
}
void TestModified::testHistoryItems()
@@ -601,20 +648,23 @@ void TestModified::testCustomData()
auto* entry = new Entry();
entry->setGroup(group);
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
QSignalSpy spyModified(db.data(), SIGNAL(databaseModified()));
db->metadata()->customData()->set("Key", "Value");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
db->metadata()->customData()->set("Key", "Value");
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
entry->customData()->set("Key", "Value");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
entry->customData()->set("Key", "Value");
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
group->customData()->set("Key", "Value");
QCOMPARE(spyModified.count(), ++spyCount);
++spyCount;
QTRY_COMPARE(spyModified.count(), spyCount);
group->customData()->set("Key", "Value");
QCOMPARE(spyModified.count(), spyCount);
QTRY_COMPARE(spyModified.count(), spyCount);
}

View File

@@ -110,37 +110,36 @@ void TestGui::init()
m_dbFilePath = m_dbFile->fileName();
m_dbFile->close();
// make sure window is activated or focus tests may fail
m_mainWindow->activateWindow();
QApplication::processEvents();
fileDialog()->setNextFileName(m_dbFilePath);
triggerAction("actionDatabaseOpen");
auto* databaseOpenWidget = m_mainWindow->findChild<QWidget*>("databaseOpenWidget");
auto* databaseOpenWidget = m_tabWidget->currentDatabaseWidget()->findChild<QWidget*>("databaseOpenWidget");
QVERIFY(databaseOpenWidget);
auto* editPassword = databaseOpenWidget->findChild<QLineEdit*>("editPassword");
QVERIFY(editPassword);
editPassword->setFocus();
QTest::keyClicks(editPassword, "a");
QTest::keyClick(editPassword, Qt::Key_Enter);
QTRY_VERIFY(m_tabWidget->currentDatabaseWidget());
m_dbWidget = m_tabWidget->currentDatabaseWidget();
m_db = m_dbWidget->database();
// make sure window is activated or focus tests may fail
m_mainWindow->activateWindow();
QApplication::processEvents();
}
// Every test ends with closing the temp database without saving
void TestGui::cleanup()
{
// DO NOT save the database
m_db->markAsClean();
MessageBox::setNextAnswer(QMessageBox::No);
triggerAction("actionDatabaseClose");
QApplication::processEvents();
MessageBox::setNextAnswer(QMessageBox::NoButton);
if (m_db) {
delete m_db;
}
if (m_dbWidget) {
delete m_dbWidget;
}
@@ -301,13 +300,14 @@ void TestGui::createDatabaseCallback()
void TestGui::testMergeDatabase()
{
// It is safe to ignore the warning this line produces
QSignalSpy dbMergeSpy(m_dbWidget.data(), SIGNAL(databaseMerged(Database*)));
QSignalSpy dbMergeSpy(m_dbWidget.data(), SIGNAL(databaseMerged(QSharedPointer<Database>)));
QApplication::processEvents();
// set file to merge from
fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/MergeDatabase.kdbx"));
triggerAction("actionDatabaseMerge");
auto* databaseOpenMergeWidget = m_mainWindow->findChild<QWidget*>("databaseOpenMergeWidget");
auto* databaseOpenMergeWidget = m_tabWidget->currentDatabaseWidget()->findChild<QWidget*>("databaseOpenMergeWidget");
auto* editPasswordMerge = databaseOpenMergeWidget->findChild<QLineEdit*>("editPassword");
QVERIFY(editPasswordMerge->isVisible());
@@ -317,7 +317,7 @@ void TestGui::testMergeDatabase()
QTest::keyClick(editPasswordMerge, Qt::Key_Enter);
QTRY_COMPARE(dbMergeSpy.count(), 1);
QTRY_VERIFY(m_tabWidget->tabText(m_tabWidget->currentIndex()).contains("*"));
QTRY_VERIFY(m_tabWidget->tabName(m_tabWidget->currentIndex()).contains("*"));
m_db = m_tabWidget->currentDatabaseWidget()->database();
@@ -352,7 +352,7 @@ void TestGui::testAutoreloadDatabase()
// the General group contains one entry from the new db data
QCOMPARE(m_db->rootGroup()->findChildByName("General")->entries().size(), 1);
QVERIFY(!m_tabWidget->tabText(m_tabWidget->currentIndex()).endsWith("*"));
QVERIFY(!m_tabWidget->tabName(m_tabWidget->currentIndex()).endsWith("*"));
// Reset the state
cleanup();
@@ -370,7 +370,7 @@ void TestGui::testAutoreloadDatabase()
// Ensure the merge did not take place
QCOMPARE(m_db->rootGroup()->findChildByName("General")->entries().size(), 0);
QVERIFY(m_tabWidget->tabText(m_tabWidget->currentIndex()).endsWith("*"));
QVERIFY(m_tabWidget->tabName(m_tabWidget->currentIndex()).endsWith("*"));
// Reset the state
cleanup();
@@ -393,13 +393,13 @@ void TestGui::testAutoreloadDatabase()
m_db = m_dbWidget->database();
QCOMPARE(m_db->rootGroup()->findChildByName("General")->entries().size(), 1);
QVERIFY(m_tabWidget->tabText(m_tabWidget->currentIndex()).endsWith("*"));
QTRY_VERIFY(m_tabWidget->tabText(m_tabWidget->currentIndex()).endsWith("*"));
}
void TestGui::testTabs()
{
QCOMPARE(m_tabWidget->count(), 1);
QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), m_dbFileName);
QCOMPARE(m_tabWidget->tabName(m_tabWidget->currentIndex()), m_dbFileName);
}
void TestGui::testEditEntry()
@@ -424,15 +424,16 @@ void TestGui::testEditEntry()
// Edit the first entry ("Sample Entry")
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
auto* titleEdit = editEntryWidget->findChild<QLineEdit*>("titleEdit");
QTest::keyClicks(titleEdit, "_test");
// Apply the edit
auto* editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox");
QVERIFY(editEntryWidgetButtonBox);
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Apply), Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
QCOMPARE(entry->title(), QString("Sample Entry_test"));
QCOMPARE(entry->historyItems().size(), ++editCount);
@@ -473,15 +474,16 @@ void TestGui::testEditEntry()
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
auto* messageWiget = editEntryWidget->findChild<MessageWidget*>("messageWidget");
QTRY_VERIFY(messageWiget->isVisible());
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
QCOMPARE(passwordEdit->text(), QString("newpass"));
passwordEdit->setText(originalPassword);
// Save the edit (press OK)
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
QApplication::processEvents();
// Confirm edit was made
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
QCOMPARE(entry->title(), QString("Sample Entry_test"));
QCOMPARE(entry->foregroundColor(), fgColor);
QCOMPARE(entryItem.data(Qt::ForegroundRole), QVariant(fgColor));
@@ -490,11 +492,11 @@ void TestGui::testEditEntry()
QCOMPARE(entry->historyItems().size(), ++editCount);
// Confirm modified indicator is showing
QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("%1*").arg(m_dbFileName));
QTRY_COMPARE(m_tabWidget->tabName(m_tabWidget->currentIndex()), QString("%1*").arg(m_dbFileName));
// Test copy & paste newline sanitization
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
titleEdit->setText("multiline\ntitle");
editEntryWidget->findChild<QLineEdit*>("usernameEdit")->setText("multiline\nusername");
editEntryWidget->findChild<QLineEdit*>("passwordEdit")->setText("multiline\npassword");
@@ -550,11 +552,11 @@ void TestGui::testSearchEditEntry()
auto* searchTextEdit = searchWidget->findChild<QLineEdit*>("searchEdit");
QTest::mouseClick(searchTextEdit, Qt::LeftButton);
QTest::keyClicks(searchTextEdit, "Doggy");
QTRY_VERIFY(m_dbWidget->isInSearchMode());
QTRY_VERIFY(m_dbWidget->isSearchActive());
// Goto "Doggy"'s edit view
QTest::keyClick(searchTextEdit, Qt::Key_Return);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
// Check the path in header is "parent-group > entry"
QCOMPARE(m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget")->findChild<QLabel*>("headerLabel")->text(),
@@ -577,7 +579,7 @@ void TestGui::testAddEntry()
// Click the new entry button and check that we enter edit mode
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
// Add entry "test" and confirm added
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
@@ -586,7 +588,7 @@ void TestGui::testAddEntry()
auto* editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox");
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
QModelIndex item = entryView->model()->index(1, 1);
Entry* entry = entryView->entryFromIndex(item);
@@ -629,7 +631,7 @@ void TestGui::testPasswordEntryEntropy()
// Click the new entry button and check that we enter edit mode
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
// Add entry "test" and confirm added
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
@@ -701,7 +703,7 @@ void TestGui::testDicewareEntryEntropy()
// Click the new entry button and check that we enter edit mode
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
// Add entry "test" and confirm added
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
@@ -736,7 +738,7 @@ void TestGui::testTotp()
auto* entryView = m_dbWidget->findChild<EntryView*>("entryView");
QCOMPARE(entryView->model()->rowCount(), 1);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
QModelIndex item = entryView->model()->index(0, 1);
Entry* entry = entryView->entryFromIndex(item);
clickIndex(item, entryView, Qt::LeftButton);
@@ -766,7 +768,7 @@ void TestGui::testTotp()
QVERIFY(entryEditWidget->isVisible());
QVERIFY(entryEditWidget->isEnabled());
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
editEntryWidget->setCurrentPage(1);
@@ -822,7 +824,7 @@ void TestGui::testSearch()
QTest::keyClicks(searchTextEdit, "ZZZ");
QTRY_COMPARE(searchTextEdit->text(), QString("ZZZ"));
QTRY_VERIFY(clearButton->isVisible());
QTRY_VERIFY(m_dbWidget->isInSearchMode());
QTRY_VERIFY(m_dbWidget->isSearchActive());
QTRY_COMPARE(entryView->model()->rowCount(), 0);
// Press the search clear button
clearButton->trigger();
@@ -834,10 +836,10 @@ void TestGui::testSearch()
QTest::keyClick(searchTextEdit, Qt::Key_Escape);
QTRY_VERIFY(searchTextEdit->text().isEmpty());
QTRY_VERIFY(searchTextEdit->hasFocus());
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
// Search for "some"
QTest::keyClicks(searchTextEdit, "some");
QTRY_VERIFY(m_dbWidget->isInSearchMode());
QTRY_VERIFY(m_dbWidget->isSearchActive());
QTRY_COMPARE(entryView->model()->rowCount(), 3);
// Search for "someTHING"
QTest::keyClicks(searchTextEdit, "THING");
@@ -894,12 +896,12 @@ void TestGui::testSearch()
// Refocus back to search edit
QTest::mouseClick(searchTextEdit, Qt::LeftButton);
QTRY_VERIFY(searchTextEdit->hasFocus());
QVERIFY(m_dbWidget->isInSearchMode());
QVERIFY(m_dbWidget->isSearchActive());
QModelIndex item = entryView->model()->index(0, 1);
Entry* entry = entryView->entryFromIndex(item);
QTest::keyClick(searchTextEdit, Qt::Key_Return);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
// Perform the edit and save it
EditEntryWidget* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
@@ -910,12 +912,12 @@ void TestGui::testSearch()
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
// Confirm the edit was made and we are back in search mode
QTRY_VERIFY(m_dbWidget->isInSearchMode());
QTRY_VERIFY(m_dbWidget->isSearchActive());
QCOMPARE(entry->title(), origTitle.append("_edited"));
// Cancel search, should return to normal view
QTest::keyClick(m_mainWindow.data(), Qt::Key_Escape);
QTRY_COMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
QTRY_COMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
}
void TestGui::testDeleteEntry()
@@ -929,7 +931,7 @@ void TestGui::testDeleteEntry()
auto* entryDeleteAction = m_mainWindow->findChild<QAction*>("actionEntryDelete");
QWidget* entryDeleteWidget = toolBar->widgetForAction(entryDeleteAction);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton);
QVERIFY(entryDeleteWidget->isVisible());
QVERIFY(entryDeleteWidget->isEnabled());
@@ -1022,7 +1024,7 @@ void TestGui::testEntryPlaceholders()
// Click the new entry button and check that we enter edit mode
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
// Add entry "test" and confirm added
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
@@ -1037,7 +1039,7 @@ void TestGui::testEntryPlaceholders()
QCOMPARE(entryView->model()->rowCount(), 2);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
QModelIndex item = entryView->model()->index(1, 1);
Entry* entry = entryView->entryFromIndex(item);
@@ -1105,7 +1107,7 @@ void TestGui::testSaveAs()
triggerAction("actionDatabaseSaveAs");
QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("testSaveAs"));
QCOMPARE(m_tabWidget->tabName(m_tabWidget->currentIndex()), QString("testSaveAs"));
checkDatabase(tmpFileName);
@@ -1122,7 +1124,7 @@ void TestGui::testSave()
QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("testSave*"));
triggerAction("actionDatabaseSave");
QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("testSave"));
QCOMPARE(m_tabWidget->tabName(m_tabWidget->currentIndex()), QString("testSave"));
checkDatabase();
}
@@ -1159,15 +1161,15 @@ void TestGui::testKeePass1Import()
fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/basic.kdb"));
triggerAction("actionImportKeePass1");
auto* keepass1OpenWidget = m_mainWindow->findChild<QWidget*>("keepass1OpenWidget");
auto* keepass1OpenWidget = m_tabWidget->currentDatabaseWidget()->findChild<QWidget*>("keepass1OpenWidget");
auto* editPassword = keepass1OpenWidget->findChild<QLineEdit*>("editPassword");
QVERIFY(editPassword);
QTest::keyClicks(editPassword, "masterpw");
QTest::keyClick(editPassword, Qt::Key_Enter);
QCOMPARE(m_tabWidget->count(), 2);
QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("basic [New database]*"));
QTRY_COMPARE(m_tabWidget->count(), 2);
QTRY_COMPARE(m_tabWidget->tabName(m_tabWidget->currentIndex()), QString("basic [New Database]*"));
// Close the KeePass1 Database
MessageBox::setNextAnswer(QMessageBox::No);
@@ -1182,7 +1184,7 @@ void TestGui::testDatabaseLocking()
MessageBox::setNextAnswer(QMessageBox::Cancel);
triggerAction("actionLockDatabases");
QCOMPARE(m_tabWidget->tabText(0).remove('&'), origDbName + " [locked]");
QCOMPARE(m_tabWidget->tabName(0), origDbName + " [Locked]");
auto* actionDatabaseMerge = m_mainWindow->findChild<QAction*>("actionDatabaseMerge", Qt::FindChildrenRecursively);
QCOMPARE(actionDatabaseMerge->isEnabled(), false);
@@ -1197,7 +1199,7 @@ void TestGui::testDatabaseLocking()
QTest::keyClicks(editPassword, "a");
QTest::keyClick(editPassword, Qt::Key_Enter);
QCOMPARE(m_tabWidget->tabText(0).remove('&'), origDbName);
QCOMPARE(m_tabWidget->tabName(0), origDbName);
actionDatabaseMerge = m_mainWindow->findChild<QAction*>("actionDatabaseMerge", Qt::FindChildrenRecursively);
QCOMPARE(actionDatabaseMerge->isEnabled(), true);
@@ -1304,10 +1306,8 @@ void TestGui::checkDatabase(QString dbFileName)
auto key = QSharedPointer<CompositeKey>::create();
key->addKey(QSharedPointer<PasswordKey>::create("a"));
KeePass2Reader reader;
QScopedPointer<Database> dbSaved(reader.readDatabase(dbFileName, key));
QVERIFY(dbSaved);
QVERIFY(!reader.hasError());
auto dbSaved = QSharedPointer<Database>::create();
QVERIFY(dbSaved->open(dbFileName, key, nullptr, false));
QCOMPARE(dbSaved->metadata()->name(), m_db->metadata()->name());
}

View File

@@ -26,6 +26,7 @@
#include <QObject>
#include <QPointer>
#include <QScopedPointer>
#include <QSharedPointer>
class Database;
class DatabaseTabWidget;
@@ -88,7 +89,7 @@ private:
QScopedPointer<MainWindow> m_mainWindow;
QPointer<DatabaseTabWidget> m_tabWidget;
QPointer<DatabaseWidget> m_dbWidget;
QPointer<Database> m_db;
QSharedPointer<Database> m_db;
QByteArray m_dbData;
QScopedPointer<TemporaryFile> m_dbFile;
QString m_dbFileName;