Merge branch 'develop'
Conflicts: CMakeLists.txt cmake/CLangFormat.cmake snapcraft.yaml src/CMakeLists.txt src/core/Database.cpp src/core/Database.h src/core/Tools.cpp src/crypto/CryptoHash.h src/crypto/ssh/ASN1Key.h src/crypto/ssh/OpenSSHKey.cpp src/format/Kdbx4Reader.cpp src/gui/DatabaseTabWidget.cpp src/gui/DatabaseTabWidget.h src/gui/DatabaseWidget.cpp src/gui/DatabaseWidget.h src/gui/DetailsWidget.cpp src/gui/DetailsWidget.ui src/gui/EditWidgetProperties.cpp src/gui/EntryPreviewWidget.cpp src/gui/EntryPreviewWidget.ui src/gui/FileDialog.cpp src/gui/dbsettings/DatabaseSettingsDialog.cpp src/gui/dbsettings/DatabaseSettingsDialog.h src/gui/group/EditGroupWidget.cpp src/gui/group/EditGroupWidget.h src/sshagent/ASN1Key.h src/sshagent/OpenSSHKey.cpp src/sshagent/SSHAgent.cpp tests/CMakeLists.txt
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
# Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
# Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -13,7 +14,11 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/../src)
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../src)
|
||||
|
||||
add_definitions(-DQT_TEST_LIB)
|
||||
|
||||
@@ -21,99 +26,98 @@ set(KEEPASSX_TEST_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data)
|
||||
configure_file(config-keepassx-tests.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keepassx-tests.h)
|
||||
|
||||
macro(parse_arguments prefix arg_names option_names)
|
||||
set(DEFAULT_ARGS)
|
||||
foreach(arg_name ${arg_names})
|
||||
set(${prefix}_${arg_name})
|
||||
endforeach(arg_name)
|
||||
foreach(option ${option_names})
|
||||
set(${prefix}_${option} FALSE)
|
||||
endforeach(option)
|
||||
set(DEFAULT_ARGS)
|
||||
foreach(arg_name ${arg_names})
|
||||
set(${prefix}_${arg_name})
|
||||
endforeach(arg_name)
|
||||
foreach(option ${option_names})
|
||||
set(${prefix}_${option} FALSE)
|
||||
endforeach(option)
|
||||
|
||||
set(current_arg_name DEFAULT_ARGS)
|
||||
set(current_arg_list)
|
||||
foreach(arg ${ARGN})
|
||||
set(larg_names ${arg_names})
|
||||
list(FIND larg_names "${arg}" is_arg_name)
|
||||
if(is_arg_name GREATER -1)
|
||||
set(${prefix}_${current_arg_name} ${current_arg_list})
|
||||
set(current_arg_name ${arg})
|
||||
set(current_arg_list)
|
||||
else()
|
||||
set(loption_names ${option_names})
|
||||
list(FIND loption_names "${arg}" is_option)
|
||||
if(is_option GREATER -1)
|
||||
set(${prefix}_${arg} TRUE)
|
||||
else(is_option GREATER -1)
|
||||
set(current_arg_list ${current_arg_list} ${arg})
|
||||
endif()
|
||||
endif()
|
||||
endforeach(arg)
|
||||
set(${prefix}_${current_arg_name} ${current_arg_list})
|
||||
set(current_arg_name DEFAULT_ARGS)
|
||||
set(current_arg_list)
|
||||
foreach(arg ${ARGN})
|
||||
set(larg_names ${arg_names})
|
||||
list(FIND larg_names "${arg}" is_arg_name)
|
||||
if(is_arg_name GREATER -1)
|
||||
set(${prefix}_${current_arg_name} ${current_arg_list})
|
||||
set(current_arg_name ${arg})
|
||||
set(current_arg_list)
|
||||
else()
|
||||
set(loption_names ${option_names})
|
||||
list(FIND loption_names "${arg}" is_option)
|
||||
if(is_option GREATER -1)
|
||||
set(${prefix}_${arg} TRUE)
|
||||
else(is_option GREATER -1)
|
||||
set(current_arg_list ${current_arg_list} ${arg})
|
||||
endif()
|
||||
endif()
|
||||
endforeach(arg)
|
||||
set(${prefix}_${current_arg_name} ${current_arg_list})
|
||||
endmacro(parse_arguments)
|
||||
|
||||
macro(add_unit_test)
|
||||
parse_arguments(TEST "NAME;SOURCES;LIBS" "" ${ARGN})
|
||||
set(_test_NAME ${TEST_NAME})
|
||||
set(_srcList ${TEST_SOURCES})
|
||||
add_executable(${_test_NAME} ${_srcList})
|
||||
target_link_libraries(${_test_NAME} ${TEST_LIBS})
|
||||
parse_arguments(TEST "NAME;SOURCES;LIBS" "" ${ARGN})
|
||||
set(_test_NAME ${TEST_NAME})
|
||||
set(_srcList ${TEST_SOURCES})
|
||||
add_executable(${_test_NAME} ${_srcList})
|
||||
target_link_libraries(${_test_NAME} ${TEST_LIBS})
|
||||
|
||||
if(NOT TEST_OUTPUT)
|
||||
set(TEST_OUTPUT plaintext)
|
||||
endif(NOT TEST_OUTPUT)
|
||||
set(TEST_OUTPUT ${TEST_OUTPUT} CACHE STRING "The output to generate when running the QTest unit tests")
|
||||
if(NOT TEST_OUTPUT)
|
||||
set(TEST_OUTPUT plaintext)
|
||||
endif(NOT TEST_OUTPUT)
|
||||
set(TEST_OUTPUT ${TEST_OUTPUT} CACHE STRING "The output to generate when running the QTest unit tests")
|
||||
|
||||
if(KDE4_TEST_OUTPUT STREQUAL "xml")
|
||||
add_test(${_test_NAME} ${_test_NAME} -xml -o ${_test_NAME}.tml)
|
||||
else(KDE4_TEST_OUTPUT STREQUAL "xml")
|
||||
add_test(${_test_NAME} ${_test_NAME})
|
||||
endif(KDE4_TEST_OUTPUT STREQUAL "xml")
|
||||
if(KDE4_TEST_OUTPUT STREQUAL "xml")
|
||||
add_test(${_test_NAME} ${_test_NAME} -xml -o ${_test_NAME}.tml)
|
||||
else(KDE4_TEST_OUTPUT STREQUAL "xml")
|
||||
add_test(${_test_NAME} ${_test_NAME})
|
||||
endif(KDE4_TEST_OUTPUT STREQUAL "xml")
|
||||
|
||||
if(NOT MSVC_IDE) #not needed for the ide
|
||||
# if the tests are EXCLUDE_FROM_ALL, add a target "buildtests" to build all tests
|
||||
if(NOT WITH_TESTS)
|
||||
get_directory_property(_buildtestsAdded BUILDTESTS_ADDED)
|
||||
if(NOT _buildtestsAdded)
|
||||
add_custom_target(buildtests)
|
||||
set_directory_properties(PROPERTIES BUILDTESTS_ADDED TRUE)
|
||||
endif()
|
||||
add_dependencies(buildtests ${_test_NAME})
|
||||
if(NOT MSVC_IDE) #not needed for the ide
|
||||
# if the tests are EXCLUDE_FROM_ALL, add a target "buildtests" to build all tests
|
||||
if(NOT WITH_TESTS)
|
||||
get_directory_property(_buildtestsAdded BUILDTESTS_ADDED)
|
||||
if(NOT _buildtestsAdded)
|
||||
add_custom_target(buildtests)
|
||||
set_directory_properties(PROPERTIES BUILDTESTS_ADDED TRUE)
|
||||
endif()
|
||||
add_dependencies(buildtests ${_test_NAME})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endmacro(add_unit_test)
|
||||
|
||||
set(TEST_LIBRARIES
|
||||
keepassx_core
|
||||
${keepasshttp_LIB}
|
||||
${autotype_LIB}
|
||||
Qt5::Core
|
||||
Qt5::Concurrent
|
||||
Qt5::Widgets
|
||||
Qt5::Test
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GPGERROR_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
)
|
||||
keepassx_core
|
||||
${keepasshttp_LIB}
|
||||
${autotype_LIB}
|
||||
Qt5::Core
|
||||
Qt5::Concurrent
|
||||
Qt5::Widgets
|
||||
Qt5::Test
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GPGERROR_LIBRARIES}
|
||||
${ZLIB_LIBRARIES})
|
||||
|
||||
set(testsupport_SOURCES TestGlobal.h modeltest.cpp FailDevice.cpp stub/TestClock.cpp stub/TestRandom.cpp)
|
||||
set(testsupport_SOURCES TestGlobal.h modeltest.cpp FailDevice.cpp mock/MockClock.cpp util/TemporaryFile.cpp stub/TestRandom.cpp)
|
||||
add_library(testsupport STATIC ${testsupport_SOURCES})
|
||||
target_link_libraries(testsupport Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test)
|
||||
|
||||
if(YUBIKEY_FOUND)
|
||||
set(TEST_LIBRARIES ${TEST_LIBRARIES} ${YUBIKEY_LIBRARIES})
|
||||
set(TEST_LIBRARIES ${TEST_LIBRARIES} ${YUBIKEY_LIBRARIES})
|
||||
endif()
|
||||
|
||||
add_unit_test(NAME testgroup SOURCES TestGroup.cpp
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testkdbx2 SOURCES TestKdbx2.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testkdbx3 SOURCES TestKeePass2Format.cpp FailDevice.cpp TestKdbx3.cpp
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testkdbx4 SOURCES TestKeePass2Format.cpp FailDevice.cpp mock/MockChallengeResponseKey.cpp TestKdbx4.cpp
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testkeys SOURCES TestKeys.cpp mock/MockChallengeResponseKey.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
@@ -132,7 +136,7 @@ add_unit_test(NAME testsymmetriccipher SOURCES TestSymmetricCipher.cpp
|
||||
|
||||
if(WITH_XC_KEESHARE)
|
||||
add_unit_test(NAME testsignature SOURCES TestSignature.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
endif()
|
||||
|
||||
add_unit_test(NAME testhashedblockstream SOURCES TestHashedBlockStream.cpp
|
||||
@@ -142,7 +146,7 @@ add_unit_test(NAME testkeepass2randomstream SOURCES TestKeePass2RandomStream.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testmodified SOURCES TestModified.cpp
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testdeletedobjects SOURCES TestDeletedObjects.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
@@ -154,21 +158,24 @@ add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
|
||||
if(WITH_XC_AUTOTYPE)
|
||||
add_unit_test(NAME testautotype SOURCES TestAutoType.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
set_target_properties(testautotype PROPERTIES ENABLE_EXPORTS ON)
|
||||
add_unit_test(NAME testautotype SOURCES TestAutoType.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
set_target_properties(testautotype PROPERTIES ENABLE_EXPORTS ON)
|
||||
endif()
|
||||
|
||||
if(WITH_XC_CRYPTO_SSH)
|
||||
add_unit_test(NAME testopensshkey SOURCES TestOpenSSHKey.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
add_unit_test(NAME testopensshkey SOURCES TestOpenSSHKey.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
endif()
|
||||
|
||||
add_unit_test(NAME testentry SOURCES TestEntry.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testmerge SOURCES TestMerge.cpp
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
LIBS testsupport ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testpasswordgenerator SOURCES TestPasswordGenerator.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testtotp SOURCES TestTotp.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
@@ -203,6 +210,11 @@ add_unit_test(NAME testdatabase SOURCES TestDatabase.cpp
|
||||
add_unit_test(NAME testtools SOURCES TestTools.cpp
|
||||
LIBS ${TEST_LIBRARIES})
|
||||
|
||||
|
||||
if(WITH_GUI_TESTS)
|
||||
add_subdirectory(gui)
|
||||
# CLI clip tests need X environment on Linux
|
||||
add_unit_test(NAME testcli SOURCES TestCli.cpp
|
||||
LIBS testsupport cli ${TEST_LIBRARIES})
|
||||
|
||||
add_subdirectory(gui)
|
||||
endif(WITH_GUI_TESTS)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
1019
tests/TestCli.cpp
Normal file
1019
tests/TestCli.cpp
Normal file
File diff suppressed because it is too large
Load Diff
73
tests/TestCli.h
Normal file
73
tests/TestCli.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program 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 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef KEEPASSXC_TESTCLI_H
|
||||
#define KEEPASSXC_TESTCLI_H
|
||||
|
||||
#include "core/Database.h"
|
||||
#include "util/TemporaryFile.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QScopedPointer>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTest>
|
||||
#include <QTextStream>
|
||||
|
||||
class TestCli : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QSharedPointer<Database> readTestDatabase() const;
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
void cleanupTestCase();
|
||||
|
||||
void testCommand();
|
||||
void testAdd();
|
||||
void testClip();
|
||||
void testDiceware();
|
||||
void testEdit();
|
||||
void testEstimate_data();
|
||||
void testEstimate();
|
||||
void testExtract();
|
||||
void testGenerate_data();
|
||||
void testGenerate();
|
||||
void testList();
|
||||
void testLocate();
|
||||
void testMerge();
|
||||
void testRemove();
|
||||
void testRemoveQuiet();
|
||||
void testShow();
|
||||
|
||||
private:
|
||||
QByteArray m_dbData;
|
||||
QByteArray m_dbData2;
|
||||
QScopedPointer<TemporaryFile> m_dbFile;
|
||||
QScopedPointer<TemporaryFile> m_dbFile2;
|
||||
QScopedPointer<TemporaryFile> m_stdoutFile;
|
||||
QScopedPointer<TemporaryFile> m_stderrFile;
|
||||
QScopedPointer<TemporaryFile> m_stdinFile;
|
||||
FILE* m_stdoutHandle = stdout;
|
||||
FILE* m_stderrHandle = stderr;
|
||||
FILE* m_stdinHandle = stdin;
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_TESTCLI_H
|
||||
@@ -50,8 +50,9 @@ void TestCryptoHash::test()
|
||||
"8d2877eec2f63b931bd47417a81a538327af927da3e"));
|
||||
|
||||
QByteArray result3 = CryptoHash::hash(source2, CryptoHash::Sha512);
|
||||
QCOMPARE(result3, QByteArray::fromHex("0d41b612584ed39ff72944c29494573e40f4bb95283455fae2e0be1e3565aa9f48057d59e6ff"
|
||||
"d777970e282871c25a549a2763e5b724794f312c97021c42f91d"));
|
||||
QCOMPARE(result3,
|
||||
QByteArray::fromHex("0d41b612584ed39ff72944c29494573e40f4bb95283455fae2e0be1e3565aa9f48057d59e6ff"
|
||||
"d777970e282871c25a549a2763e5b724794f312c97021c42f91d"));
|
||||
|
||||
CryptoHash cryptoHash4(CryptoHash::Sha512);
|
||||
cryptoHash4.addData(QString("KeePa").toLatin1());
|
||||
|
||||
@@ -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");
|
||||
@@ -64,9 +62,10 @@ void TestCsvExporter::testExport()
|
||||
QVERIFY(buffer.open(QIODevice::ReadWrite));
|
||||
m_csvExporter->exportDatabase(&buffer, m_db);
|
||||
|
||||
QString expectedResult =
|
||||
QString().append(ExpectedHeaderLine).append("\"Test Group Name\",\"Test Entry Title\",\"Test Username\",\"Test "
|
||||
"Password\",\"http://test.url\",\"Test Notes\"\n");
|
||||
QString expectedResult = 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 +82,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 +99,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"));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -343,8 +343,7 @@ void TestEntry::testResolveReferencePlaceholders()
|
||||
tstEntry->setGroup(root);
|
||||
tstEntry->setUuid(QUuid::createUuid());
|
||||
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuidToHex())),
|
||||
entry1->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuidToHex())), entry1->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry1->title())), entry1->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@U:%1}").arg(entry1->username())), entry1->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@P:%1}").arg(entry1->password())), entry1->title());
|
||||
@@ -354,8 +353,7 @@ void TestEntry::testResolveReferencePlaceholders()
|
||||
QString("{REF:T@O:%1}").arg(entry1->attributes()->value("CustomAttribute1"))),
|
||||
entry1->title());
|
||||
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuidToHex())),
|
||||
entry1->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuidToHex())), entry1->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry1->title())), entry1->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@U:%1}").arg(entry1->username())),
|
||||
entry1->username());
|
||||
@@ -364,8 +362,7 @@ void TestEntry::testResolveReferencePlaceholders()
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@A:%1}").arg(entry1->url())), entry1->url());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@N:%1}").arg(entry1->notes())), entry1->notes());
|
||||
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry2->uuidToHex())),
|
||||
entry2->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry2->uuidToHex())), entry2->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry2->title())), entry2->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@U:%1}").arg(entry2->username())), entry2->title());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@P:%1}").arg(entry2->password())), entry2->title());
|
||||
@@ -383,23 +380,38 @@ void TestEntry::testResolveReferencePlaceholders()
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@A:%1}").arg(entry2->url())), entry2->url());
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@N:%1}").arg(entry2->notes())), entry2->notes());
|
||||
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuidToHex())), entry3->attributes()->value("AttributeTitle"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuidToHex())), entry3->attributes()->value("AttributeUsername"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuidToHex())), entry3->attributes()->value("AttributePassword"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuidToHex())), entry3->attributes()->value("AttributeUrl"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuidToHex())), entry3->attributes()->value("AttributeNotes"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuidToHex())),
|
||||
entry3->attributes()->value("AttributeTitle"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuidToHex())),
|
||||
entry3->attributes()->value("AttributeUsername"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuidToHex())),
|
||||
entry3->attributes()->value("AttributePassword"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuidToHex())),
|
||||
entry3->attributes()->value("AttributeUrl"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuidToHex())),
|
||||
entry3->attributes()->value("AttributeNotes"));
|
||||
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuidToHex().toUpper())), entry3->attributes()->value("AttributeTitle"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuidToHex().toUpper())), entry3->attributes()->value("AttributeUsername"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuidToHex().toUpper())), entry3->attributes()->value("AttributePassword"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuidToHex().toUpper())), entry3->attributes()->value("AttributeUrl"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuidToHex().toUpper())), entry3->attributes()->value("AttributeNotes"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuidToHex().toUpper())),
|
||||
entry3->attributes()->value("AttributeTitle"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuidToHex().toUpper())),
|
||||
entry3->attributes()->value("AttributeUsername"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuidToHex().toUpper())),
|
||||
entry3->attributes()->value("AttributePassword"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuidToHex().toUpper())),
|
||||
entry3->attributes()->value("AttributeUrl"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuidToHex().toUpper())),
|
||||
entry3->attributes()->value("AttributeNotes"));
|
||||
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:t@i:%1}").arg(entry3->uuidToHex().toLower())), entry3->attributes()->value("AttributeTitle"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:u@i:%1}").arg(entry3->uuidToHex().toLower())), entry3->attributes()->value("AttributeUsername"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:p@i:%1}").arg(entry3->uuidToHex().toLower())), entry3->attributes()->value("AttributePassword"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:a@i:%1}").arg(entry3->uuidToHex().toLower())), entry3->attributes()->value("AttributeUrl"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:n@i:%1}").arg(entry3->uuidToHex().toLower())), entry3->attributes()->value("AttributeNotes"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:t@i:%1}").arg(entry3->uuidToHex().toLower())),
|
||||
entry3->attributes()->value("AttributeTitle"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:u@i:%1}").arg(entry3->uuidToHex().toLower())),
|
||||
entry3->attributes()->value("AttributeUsername"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:p@i:%1}").arg(entry3->uuidToHex().toLower())),
|
||||
entry3->attributes()->value("AttributePassword"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:a@i:%1}").arg(entry3->uuidToHex().toLower())),
|
||||
entry3->attributes()->value("AttributeUrl"));
|
||||
QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:n@i:%1}").arg(entry3->uuidToHex().toLower())),
|
||||
entry3->attributes()->value("AttributeNotes"));
|
||||
}
|
||||
|
||||
void TestEntry::testResolveNonIdPlaceholdersToUuid()
|
||||
@@ -466,8 +478,7 @@ void TestEntry::testResolveNonIdPlaceholdersToUuid()
|
||||
newEntry->setGroup(root);
|
||||
newEntry->setNotes(newEntryNotesRaw);
|
||||
|
||||
const QString newEntryNotesResolved =
|
||||
newEntry->resolveMultiplePlaceholders(newEntry->notes());
|
||||
const QString newEntryNotesResolved = newEntry->resolveMultiplePlaceholders(newEntry->notes());
|
||||
QCOMPARE(newEntryNotesResolved, referencedEntry->uuidToHex());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ void TestEntryModel::testProxyModel()
|
||||
|
||||
QList<Entry*> entryList;
|
||||
entryList << entry;
|
||||
modelSource->setEntryList(entryList);
|
||||
modelSource->setEntries(entryList);
|
||||
|
||||
/**
|
||||
* @author Fonic <https://github.com/fonic>
|
||||
@@ -346,7 +346,7 @@ void TestEntryModel::testDatabaseDelete()
|
||||
Entry* entry2 = new Entry();
|
||||
entry2->setGroup(db2->rootGroup());
|
||||
|
||||
model->setEntryList(QList<Entry*>() << entry1 << entry2);
|
||||
model->setEntries(QList<Entry*>() << entry1 << entry2);
|
||||
|
||||
QCOMPARE(model->rowCount(), 2);
|
||||
|
||||
|
||||
@@ -20,25 +20,34 @@
|
||||
|
||||
QTEST_GUILESS_MAIN(TestEntrySearcher)
|
||||
|
||||
void TestEntrySearcher::initTestCase()
|
||||
void TestEntrySearcher::init()
|
||||
{
|
||||
m_groupRoot = new Group();
|
||||
m_rootGroup = new Group();
|
||||
}
|
||||
|
||||
void TestEntrySearcher::cleanupTestCase()
|
||||
void TestEntrySearcher::cleanup()
|
||||
{
|
||||
delete m_groupRoot;
|
||||
delete m_rootGroup;
|
||||
}
|
||||
|
||||
void TestEntrySearcher::testSearch()
|
||||
{
|
||||
/**
|
||||
* Root
|
||||
* - group1 (search disabled)
|
||||
* - group11
|
||||
* - group2
|
||||
* - group21
|
||||
* - group211
|
||||
* - group2111
|
||||
*/
|
||||
Group* group1 = new Group();
|
||||
Group* group2 = new Group();
|
||||
Group* group3 = new Group();
|
||||
|
||||
group1->setParent(m_groupRoot);
|
||||
group2->setParent(m_groupRoot);
|
||||
group3->setParent(m_groupRoot);
|
||||
group1->setParent(m_rootGroup);
|
||||
group2->setParent(m_rootGroup);
|
||||
group3->setParent(m_rootGroup);
|
||||
|
||||
Group* group11 = new Group();
|
||||
|
||||
@@ -53,50 +62,74 @@ void TestEntrySearcher::testSearch()
|
||||
group2111->setParent(group211);
|
||||
|
||||
group1->setSearchingEnabled(Group::Disable);
|
||||
group11->setSearchingEnabled(Group::Enable);
|
||||
|
||||
Entry* eRoot = new Entry();
|
||||
eRoot->setNotes("test search term test");
|
||||
eRoot->setGroup(m_groupRoot);
|
||||
eRoot->setTitle("test search term test");
|
||||
eRoot->setGroup(m_rootGroup);
|
||||
|
||||
Entry* eRoot2 = new Entry();
|
||||
eRoot2->setNotes("test term test");
|
||||
eRoot2->setGroup(m_groupRoot);
|
||||
eRoot2->setGroup(m_rootGroup);
|
||||
|
||||
// Searching is disabled for these
|
||||
Entry* e1 = new Entry();
|
||||
e1->setNotes("test search term test");
|
||||
e1->setUsername("test search term test");
|
||||
e1->setGroup(group1);
|
||||
|
||||
Entry* e11 = new Entry();
|
||||
e11->setNotes("test search term test");
|
||||
e11->setGroup(group11);
|
||||
// End searching disabled
|
||||
|
||||
Entry* e2111 = new Entry();
|
||||
e2111->setNotes("test search term test");
|
||||
e2111->setTitle("test search term test");
|
||||
e2111->setGroup(group2111);
|
||||
|
||||
Entry* e2111b = new Entry();
|
||||
e2111b->setNotes("test search test");
|
||||
e2111b->setUsername("user123");
|
||||
e2111b->setPassword("testpass");
|
||||
e2111b->setGroup(group2111);
|
||||
|
||||
Entry* e3 = new Entry();
|
||||
e3->setNotes("test search term test");
|
||||
e3->setUrl("test search term test");
|
||||
e3->setGroup(group3);
|
||||
|
||||
Entry* e3b = new Entry();
|
||||
e3b->setNotes("test search test");
|
||||
e3b->setTitle("test search test");
|
||||
e3b->setUsername("test@email.com");
|
||||
e3b->setPassword("realpass");
|
||||
e3b->setGroup(group3);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("search term", m_groupRoot, Qt::CaseInsensitive);
|
||||
// Simple search term testing
|
||||
m_searchResult = m_entrySearcher.search("search", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 5);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("search term", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 3);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("search term", group211, Qt::CaseInsensitive);
|
||||
m_searchResult = m_entrySearcher.search("search term", group211);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("search term", group11, Qt::CaseInsensitive);
|
||||
// Test advanced search terms
|
||||
m_searchResult = m_entrySearcher.search("password:testpass", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("search term", group1, Qt::CaseInsensitive);
|
||||
m_searchResult = m_entrySearcher.search("!user:email.com", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 5);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("*user:\".*@.*\\.com\"", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("+user:email", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 0);
|
||||
|
||||
// Terms are logical AND together
|
||||
m_searchResult = m_entrySearcher.search("password:pass user:user", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
|
||||
// Parent group has search disabled
|
||||
m_searchResult = m_entrySearcher.search("search term", group11);
|
||||
QCOMPARE(m_searchResult.count(), 0);
|
||||
}
|
||||
|
||||
@@ -105,38 +138,74 @@ void TestEntrySearcher::testAndConcatenationInSearch()
|
||||
Entry* entry = new Entry();
|
||||
entry->setNotes("abc def ghi");
|
||||
entry->setTitle("jkl");
|
||||
entry->setGroup(m_groupRoot);
|
||||
entry->setGroup(m_rootGroup);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("", m_groupRoot, Qt::CaseInsensitive);
|
||||
m_searchResult = m_entrySearcher.search("", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("def", m_groupRoot, Qt::CaseInsensitive);
|
||||
m_searchResult = m_entrySearcher.search("def", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
|
||||
m_searchResult = m_entrySearcher.search(" abc ghi ", m_groupRoot, Qt::CaseInsensitive);
|
||||
m_searchResult = m_entrySearcher.search(" abc ghi ", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("ghi ef", m_groupRoot, Qt::CaseInsensitive);
|
||||
m_searchResult = m_entrySearcher.search("ghi ef", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("abc ef xyz", m_groupRoot, Qt::CaseInsensitive);
|
||||
m_searchResult = m_entrySearcher.search("abc ef xyz", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 0);
|
||||
|
||||
m_searchResult = m_entrySearcher.search("abc kl", m_groupRoot, Qt::CaseInsensitive);
|
||||
m_searchResult = m_entrySearcher.search("abc kl", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
}
|
||||
|
||||
void TestEntrySearcher::testAllAttributesAreSearched()
|
||||
{
|
||||
Entry* entry = new Entry();
|
||||
entry->setGroup(m_groupRoot);
|
||||
entry->setGroup(m_rootGroup);
|
||||
|
||||
entry->setTitle("testTitle");
|
||||
entry->setUsername("testUsername");
|
||||
entry->setUrl("testUrl");
|
||||
entry->setNotes("testNote");
|
||||
|
||||
m_searchResult =
|
||||
m_entrySearcher.search("testTitle testUsername testUrl testNote", m_groupRoot, Qt::CaseInsensitive);
|
||||
// Default is to AND all terms together
|
||||
m_searchResult = m_entrySearcher.search("testTitle testUsername testUrl testNote", m_rootGroup);
|
||||
QCOMPARE(m_searchResult.count(), 1);
|
||||
}
|
||||
|
||||
void TestEntrySearcher::testSearchTermParser()
|
||||
{
|
||||
// Test standard search terms
|
||||
auto terms = m_entrySearcher.parseSearchTerms("-test \"quoted \\\"string\\\"\" user:user pass:\"test me\" noquote ");
|
||||
|
||||
QCOMPARE(terms.length(), 5);
|
||||
|
||||
QCOMPARE(terms[0]->field, EntrySearcher::Field::Undefined);
|
||||
QCOMPARE(terms[0]->word, QString("test"));
|
||||
QCOMPARE(terms[0]->exclude, true);
|
||||
|
||||
QCOMPARE(terms[1]->field, EntrySearcher::Field::Undefined);
|
||||
QCOMPARE(terms[1]->word, QString("quoted \\\"string\\\""));
|
||||
QCOMPARE(terms[1]->exclude, false);
|
||||
|
||||
QCOMPARE(terms[2]->field, EntrySearcher::Field::Username);
|
||||
QCOMPARE(terms[2]->word, QString("user"));
|
||||
|
||||
QCOMPARE(terms[3]->field, EntrySearcher::Field::Password);
|
||||
QCOMPARE(terms[3]->word, QString("test me"));
|
||||
|
||||
QCOMPARE(terms[4]->field, EntrySearcher::Field::Undefined);
|
||||
QCOMPARE(terms[4]->word, QString("noquote"));
|
||||
|
||||
// Test wildcard and regex search terms
|
||||
terms = m_entrySearcher.parseSearchTerms("+url:*.google.com *user:\\d+\\w{2}");
|
||||
|
||||
QCOMPARE(terms.length(), 2);
|
||||
|
||||
QCOMPARE(terms[0]->field, EntrySearcher::Field::Url);
|
||||
QCOMPARE(terms[0]->regex.pattern(), QString("^.*\\.google\\.com$"));
|
||||
|
||||
QCOMPARE(terms[1]->field, EntrySearcher::Field::Username);
|
||||
QCOMPARE(terms[1]->regex.pattern(), QString("\\d+\\w{2}"));
|
||||
}
|
||||
|
||||
@@ -28,15 +28,16 @@ class TestEntrySearcher : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
void testAndConcatenationInSearch();
|
||||
void testSearch();
|
||||
void testAllAttributesAreSearched();
|
||||
void testSearchTermParser();
|
||||
|
||||
private:
|
||||
Group* m_groupRoot;
|
||||
Group* m_rootGroup;
|
||||
EntrySearcher m_entrySearcher;
|
||||
QList<Entry*> m_searchResult;
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
namespace QTest
|
||||
{
|
||||
|
||||
|
||||
template <> inline char* toString(const Group::TriState& triState)
|
||||
{
|
||||
QString value;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include "TestGroup.h"
|
||||
#include "TestGlobal.h"
|
||||
#include "stub/TestClock.h"
|
||||
#include "mock/MockClock.h"
|
||||
|
||||
#include <QSignalSpy>
|
||||
|
||||
@@ -29,7 +29,7 @@ QTEST_GUILESS_MAIN(TestGroup)
|
||||
|
||||
namespace
|
||||
{
|
||||
TestClock* m_clock = nullptr;
|
||||
MockClock* m_clock = nullptr;
|
||||
}
|
||||
|
||||
void TestGroup::initTestCase()
|
||||
@@ -42,13 +42,13 @@ void TestGroup::initTestCase()
|
||||
void TestGroup::init()
|
||||
{
|
||||
Q_ASSERT(m_clock == nullptr);
|
||||
m_clock = new TestClock(2010, 5, 5, 10, 30, 10);
|
||||
TestClock::setup(m_clock);
|
||||
m_clock = new MockClock(2010, 5, 5, 10, 30, 10);
|
||||
MockClock::setup(m_clock);
|
||||
}
|
||||
|
||||
void TestGroup::cleanup()
|
||||
{
|
||||
TestClock::teardown();
|
||||
MockClock::teardown();
|
||||
m_clock = nullptr;
|
||||
}
|
||||
|
||||
@@ -493,57 +493,64 @@ void TestGroup::testFindEntry()
|
||||
|
||||
Entry* entry;
|
||||
|
||||
entry = db->rootGroup()->findEntry(entry1->uuidToHex());
|
||||
QVERIFY(entry != nullptr);
|
||||
entry = db->rootGroup()->findEntryByUuid(entry1->uuid());
|
||||
QVERIFY(entry);
|
||||
QCOMPARE(entry->title(), QString("entry1"));
|
||||
|
||||
entry = db->rootGroup()->findEntry(QString("entry1"));
|
||||
QVERIFY(entry != nullptr);
|
||||
entry = db->rootGroup()->findEntryByPath(QString("entry1"));
|
||||
QVERIFY(entry);
|
||||
QCOMPARE(entry->title(), QString("entry1"));
|
||||
|
||||
// We also can find the entry with the leading slash.
|
||||
entry = db->rootGroup()->findEntry(QString("/entry1"));
|
||||
QVERIFY(entry != nullptr);
|
||||
entry = db->rootGroup()->findEntryByPath(QString("/entry1"));
|
||||
QVERIFY(entry);
|
||||
QCOMPARE(entry->title(), QString("entry1"));
|
||||
|
||||
// But two slashes should not be accepted.
|
||||
entry = db->rootGroup()->findEntry(QString("//entry1"));
|
||||
QVERIFY(entry == nullptr);
|
||||
entry = db->rootGroup()->findEntryByPath(QString("//entry1"));
|
||||
QVERIFY(!entry);
|
||||
|
||||
entry = db->rootGroup()->findEntry(entry2->uuidToHex());
|
||||
QVERIFY(entry != nullptr);
|
||||
entry = db->rootGroup()->findEntryByUuid(entry2->uuid());
|
||||
QVERIFY(entry);
|
||||
QCOMPARE(entry->title(), QString("entry2"));
|
||||
|
||||
entry = db->rootGroup()->findEntry(QString("group1/entry2"));
|
||||
QVERIFY(entry != nullptr);
|
||||
entry = db->rootGroup()->findEntryByPath(QString("group1/entry2"));
|
||||
QVERIFY(entry);
|
||||
QCOMPARE(entry->title(), QString("entry2"));
|
||||
|
||||
entry = db->rootGroup()->findEntry(QString("/entry2"));
|
||||
QVERIFY(entry == nullptr);
|
||||
entry = db->rootGroup()->findEntryByPath(QString("/entry2"));
|
||||
QVERIFY(!entry);
|
||||
|
||||
// We also can find the entry with the leading slash.
|
||||
entry = db->rootGroup()->findEntry(QString("/group1/entry2"));
|
||||
QVERIFY(entry != nullptr);
|
||||
entry = db->rootGroup()->findEntryByPath(QString("/group1/entry2"));
|
||||
QVERIFY(entry);
|
||||
QCOMPARE(entry->title(), QString("entry2"));
|
||||
|
||||
// Should also find the entry only by title.
|
||||
entry = db->rootGroup()->findEntry(QString("entry2"));
|
||||
QVERIFY(entry != nullptr);
|
||||
entry = db->rootGroup()->findEntryByPath(QString("entry2"));
|
||||
QVERIFY(entry);
|
||||
QCOMPARE(entry->title(), QString("entry2"));
|
||||
|
||||
entry = db->rootGroup()->findEntry(QString("invalid/path/to/entry2"));
|
||||
QVERIFY(entry == nullptr);
|
||||
entry = db->rootGroup()->findEntryByPath(QString("invalid/path/to/entry2"));
|
||||
QVERIFY(!entry);
|
||||
|
||||
entry = db->rootGroup()->findEntry(QString("entry27"));
|
||||
QVERIFY(entry == nullptr);
|
||||
entry = db->rootGroup()->findEntryByPath(QString("entry27"));
|
||||
QVERIFY(!entry);
|
||||
|
||||
// A valid UUID that does not exist in this database.
|
||||
entry = db->rootGroup()->findEntry(QString("febfb01ebcdf9dbd90a3f1579dc75281"));
|
||||
QVERIFY(entry == nullptr);
|
||||
entry = db->rootGroup()->findEntryByUuid(QUuid("febfb01ebcdf9dbd90a3f1579dc75281"));
|
||||
QVERIFY(!entry);
|
||||
|
||||
// An invalid UUID.
|
||||
entry = db->rootGroup()->findEntry(QString("febfb01ebcdf9dbd90a3f1579dc"));
|
||||
QVERIFY(entry == nullptr);
|
||||
entry = db->rootGroup()->findEntryByUuid(QUuid("febfb01ebcdf9dbd90a3f1579dc"));
|
||||
QVERIFY(!entry);
|
||||
|
||||
// Empty strings
|
||||
entry = db->rootGroup()->findEntryByUuid({});
|
||||
QVERIFY(!entry);
|
||||
|
||||
entry = db->rootGroup()->findEntryByPath({});
|
||||
QVERIFY(!entry);
|
||||
}
|
||||
|
||||
void TestGroup::testFindGroupByPath()
|
||||
@@ -561,51 +568,51 @@ void TestGroup::testFindGroupByPath()
|
||||
Group* group;
|
||||
|
||||
group = db->rootGroup()->findGroupByPath("/");
|
||||
QVERIFY(group != nullptr);
|
||||
QVERIFY(group);
|
||||
QCOMPARE(group->uuid(), db->rootGroup()->uuid());
|
||||
|
||||
// We also accept it if the leading slash is missing.
|
||||
group = db->rootGroup()->findGroupByPath("");
|
||||
QVERIFY(group != nullptr);
|
||||
QVERIFY(group);
|
||||
QCOMPARE(group->uuid(), db->rootGroup()->uuid());
|
||||
|
||||
group = db->rootGroup()->findGroupByPath("/group1/");
|
||||
QVERIFY(group != nullptr);
|
||||
QVERIFY(group);
|
||||
QCOMPARE(group->uuid(), group1->uuid());
|
||||
|
||||
// We also accept it if the leading slash is missing.
|
||||
group = db->rootGroup()->findGroupByPath("group1/");
|
||||
QVERIFY(group != nullptr);
|
||||
QVERIFY(group);
|
||||
QCOMPARE(group->uuid(), group1->uuid());
|
||||
|
||||
// Too many slashes at the end
|
||||
group = db->rootGroup()->findGroupByPath("group1//");
|
||||
QVERIFY(group == nullptr);
|
||||
QVERIFY(!group);
|
||||
|
||||
// Missing a slash at the end.
|
||||
group = db->rootGroup()->findGroupByPath("/group1");
|
||||
QVERIFY(group != nullptr);
|
||||
QVERIFY(group);
|
||||
QCOMPARE(group->uuid(), group1->uuid());
|
||||
|
||||
// Too many slashes at the start
|
||||
group = db->rootGroup()->findGroupByPath("//group1");
|
||||
QVERIFY(group == nullptr);
|
||||
QVERIFY(!group);
|
||||
|
||||
group = db->rootGroup()->findGroupByPath("/group1/group2/");
|
||||
QVERIFY(group != nullptr);
|
||||
QVERIFY(group);
|
||||
QCOMPARE(group->uuid(), group2->uuid());
|
||||
|
||||
// We also accept it if the leading slash is missing.
|
||||
group = db->rootGroup()->findGroupByPath("group1/group2/");
|
||||
QVERIFY(group != nullptr);
|
||||
QVERIFY(group);
|
||||
QCOMPARE(group->uuid(), group2->uuid());
|
||||
|
||||
group = db->rootGroup()->findGroupByPath("group1/group2");
|
||||
QVERIFY(group != nullptr);
|
||||
QVERIFY(group);
|
||||
QCOMPARE(group->uuid(), group2->uuid());
|
||||
|
||||
group = db->rootGroup()->findGroupByPath("invalid");
|
||||
QVERIFY(group == nullptr);
|
||||
QVERIFY(!group);
|
||||
}
|
||||
|
||||
void TestGroup::testPrint()
|
||||
@@ -697,7 +704,7 @@ void TestGroup::testLocate()
|
||||
QVERIFY(results.contains("/entry1"));
|
||||
|
||||
results = db->rootGroup()->locate("invalid");
|
||||
QVERIFY(results.size() == 0);
|
||||
QVERIFY(results.isEmpty());
|
||||
|
||||
results = db->rootGroup()->locate("google");
|
||||
QVERIFY(results.size() == 1);
|
||||
@@ -725,37 +732,37 @@ void TestGroup::testAddEntryWithPath()
|
||||
group2->setParent(group1);
|
||||
|
||||
Entry* entry = db->rootGroup()->addEntryWithPath("entry1");
|
||||
QVERIFY(entry != nullptr);
|
||||
QVERIFY(entry);
|
||||
QVERIFY(!entry->uuid().isNull());
|
||||
|
||||
entry = db->rootGroup()->addEntryWithPath("entry1");
|
||||
QVERIFY(entry == nullptr);
|
||||
QVERIFY(!entry);
|
||||
|
||||
entry = db->rootGroup()->addEntryWithPath("/entry1");
|
||||
QVERIFY(entry == nullptr);
|
||||
QVERIFY(!entry);
|
||||
|
||||
entry = db->rootGroup()->addEntryWithPath("entry2");
|
||||
QVERIFY(entry != nullptr);
|
||||
QVERIFY(entry);
|
||||
QVERIFY(entry->title() == "entry2");
|
||||
QVERIFY(!entry->uuid().isNull());
|
||||
|
||||
entry = db->rootGroup()->addEntryWithPath("/entry3");
|
||||
QVERIFY(entry != nullptr);
|
||||
QVERIFY(entry);
|
||||
QVERIFY(entry->title() == "entry3");
|
||||
QVERIFY(!entry->uuid().isNull());
|
||||
|
||||
entry = db->rootGroup()->addEntryWithPath("/group1/entry4");
|
||||
QVERIFY(entry != nullptr);
|
||||
QVERIFY(entry);
|
||||
QVERIFY(entry->title() == "entry4");
|
||||
QVERIFY(!entry->uuid().isNull());
|
||||
|
||||
entry = db->rootGroup()->addEntryWithPath("/group1/group2/entry5");
|
||||
QVERIFY(entry != nullptr);
|
||||
QVERIFY(entry);
|
||||
QVERIFY(entry->title() == "entry5");
|
||||
QVERIFY(!entry->uuid().isNull());
|
||||
|
||||
entry = db->rootGroup()->addEntryWithPath("/group1/invalid_group/entry6");
|
||||
QVERIFY(entry == nullptr);
|
||||
QVERIFY(!entry);
|
||||
|
||||
delete db;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ private slots:
|
||||
void testFormat200Upgrade();
|
||||
|
||||
private:
|
||||
void verifyKdbx2Db(Database* db);
|
||||
void verifyKdbx2Db(QSharedPointer<Database> db);
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_TEST_KDBX2_H
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())));
|
||||
}
|
||||
@@ -199,12 +201,12 @@ void TestKdbx4::testFormat400Upgrade_data()
|
||||
auto constexpr kdbx3 = KeePass2::FILE_VERSION_3_1 & KeePass2::FILE_VERSION_CRITICAL_MASK;
|
||||
auto constexpr kdbx4 = KeePass2::FILE_VERSION_4 & KeePass2::FILE_VERSION_CRITICAL_MASK;
|
||||
|
||||
QTest::newRow("Argon2 + AES") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_AES << false << kdbx4;
|
||||
QTest::newRow("AES-KDF + AES") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_AES << false << kdbx4;
|
||||
QTest::newRow("AES-KDF (legacy) + AES") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_AES << false << kdbx3;
|
||||
QTest::newRow("Argon2 + AES + CustomData") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_AES << true << kdbx4;
|
||||
QTest::newRow("AES-KDF + AES + CustomData") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_AES << true << kdbx4;
|
||||
QTest::newRow("AES-KDF (legacy) + AES + CustomData") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_AES << true << kdbx4;
|
||||
QTest::newRow("Argon2 + AES") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_AES256 << false << kdbx4;
|
||||
QTest::newRow("AES-KDF + AES") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_AES256 << false << kdbx4;
|
||||
QTest::newRow("AES-KDF (legacy) + AES") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_AES256 << false << kdbx3;
|
||||
QTest::newRow("Argon2 + AES + CustomData") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_AES256 << true << kdbx4;
|
||||
QTest::newRow("AES-KDF + AES + CustomData") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_AES256 << true << kdbx4;
|
||||
QTest::newRow("AES-KDF (legacy) + AES + CustomData") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_AES256 << true << kdbx4;
|
||||
|
||||
QTest::newRow("Argon2 + ChaCha20") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_CHACHA20 << false << kdbx4;
|
||||
QTest::newRow("AES-KDF + ChaCha20") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_CHACHA20 << false << kdbx4;
|
||||
@@ -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()));
|
||||
}
|
||||
@@ -317,11 +320,11 @@ void TestKdbx4::testUpgradeMasterKeyIntegrity_data()
|
||||
QTest::newRow("Upgrade (explicit): kdf-argon2") << QString("kdf-argon2") << KeePass2::FILE_VERSION_4;
|
||||
QTest::newRow("Upgrade (explicit): kdf-aes-kdbx4") << QString("kdf-aes-kdbx4") << KeePass2::FILE_VERSION_4;
|
||||
QTest::newRow("Upgrade (implicit): public-customdata") << QString("public-customdata") << KeePass2::FILE_VERSION_4;
|
||||
QTest::newRow("Upgrade (implicit): rootgroup-customdata") << QString("rootgroup-customdata")
|
||||
<< KeePass2::FILE_VERSION_4;
|
||||
QTest::newRow("Upgrade (implicit): rootgroup-customdata")
|
||||
<< QString("rootgroup-customdata") << KeePass2::FILE_VERSION_4;
|
||||
QTest::newRow("Upgrade (implicit): group-customdata") << QString("group-customdata") << KeePass2::FILE_VERSION_4;
|
||||
QTest::newRow("Upgrade (implicit): rootentry-customdata") << QString("rootentry-customdata")
|
||||
<< KeePass2::FILE_VERSION_4;
|
||||
QTest::newRow("Upgrade (implicit): rootentry-customdata")
|
||||
<< QString("rootentry-customdata") << KeePass2::FILE_VERSION_4;
|
||||
QTest::newRow("Upgrade (implicit): entry-customdata") << QString("entry-customdata") << KeePass2::FILE_VERSION_4;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,18 +254,20 @@ 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));
|
||||
|
||||
auto key = QSharedPointer<CompositeKey>::create();
|
||||
if (!password.isNull()) {
|
||||
if (!password.isEmpty()) {
|
||||
key->addKey(QSharedPointer<PasswordKey>::create(password));
|
||||
}
|
||||
if (!keyfileName.isEmpty()) {
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "TestKeePass2Format.h"
|
||||
#include "TestGlobal.h"
|
||||
#include "stub/TestClock.h"
|
||||
#include "mock/MockClock.h"
|
||||
|
||||
#include "core/Metadata.h"
|
||||
#include "crypto/Crypto.h"
|
||||
@@ -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();
|
||||
@@ -78,14 +78,14 @@ void TestKeePass2Format::testXmlMetadata()
|
||||
{
|
||||
QCOMPARE(m_xmlDb->metadata()->generator(), QString("KeePass"));
|
||||
QCOMPARE(m_xmlDb->metadata()->name(), QString("ANAME"));
|
||||
QCOMPARE(m_xmlDb->metadata()->nameChanged(), TestClock::datetimeUtc(2010, 8, 8, 17, 24, 53));
|
||||
QCOMPARE(m_xmlDb->metadata()->nameChanged(), MockClock::datetimeUtc(2010, 8, 8, 17, 24, 53));
|
||||
QCOMPARE(m_xmlDb->metadata()->description(), QString("ADESC"));
|
||||
QCOMPARE(m_xmlDb->metadata()->descriptionChanged(), TestClock::datetimeUtc(2010, 8, 8, 17, 27, 12));
|
||||
QCOMPARE(m_xmlDb->metadata()->descriptionChanged(), MockClock::datetimeUtc(2010, 8, 8, 17, 27, 12));
|
||||
QCOMPARE(m_xmlDb->metadata()->defaultUserName(), QString("DEFUSERNAME"));
|
||||
QCOMPARE(m_xmlDb->metadata()->defaultUserNameChanged(), TestClock::datetimeUtc(2010, 8, 8, 17, 27, 45));
|
||||
QCOMPARE(m_xmlDb->metadata()->defaultUserNameChanged(), MockClock::datetimeUtc(2010, 8, 8, 17, 27, 45));
|
||||
QCOMPARE(m_xmlDb->metadata()->maintenanceHistoryDays(), 127);
|
||||
QCOMPARE(m_xmlDb->metadata()->color(), QColor(0xff, 0xef, 0x00));
|
||||
QCOMPARE(m_xmlDb->metadata()->masterKeyChanged(), TestClock::datetimeUtc(2012, 4, 5, 17, 9, 34));
|
||||
QCOMPARE(m_xmlDb->metadata()->masterKeyChanged(), MockClock::datetimeUtc(2012, 4, 5, 17, 9, 34));
|
||||
QCOMPARE(m_xmlDb->metadata()->masterKeyChangeRec(), 101);
|
||||
QCOMPARE(m_xmlDb->metadata()->masterKeyChangeForce(), -1);
|
||||
QCOMPARE(m_xmlDb->metadata()->protectTitle(), false);
|
||||
@@ -96,9 +96,9 @@ void TestKeePass2Format::testXmlMetadata()
|
||||
QCOMPARE(m_xmlDb->metadata()->recycleBinEnabled(), true);
|
||||
QVERIFY(m_xmlDb->metadata()->recycleBin() != nullptr);
|
||||
QCOMPARE(m_xmlDb->metadata()->recycleBin()->name(), QString("Recycle Bin"));
|
||||
QCOMPARE(m_xmlDb->metadata()->recycleBinChanged(), TestClock::datetimeUtc(2010, 8, 25, 16, 12, 57));
|
||||
QCOMPARE(m_xmlDb->metadata()->recycleBinChanged(), MockClock::datetimeUtc(2010, 8, 25, 16, 12, 57));
|
||||
QVERIFY(m_xmlDb->metadata()->entryTemplatesGroup() == nullptr);
|
||||
QCOMPARE(m_xmlDb->metadata()->entryTemplatesGroupChanged(), TestClock::datetimeUtc(2010, 8, 8, 17, 24, 19));
|
||||
QCOMPARE(m_xmlDb->metadata()->entryTemplatesGroupChanged(), MockClock::datetimeUtc(2010, 8, 8, 17, 24, 19));
|
||||
QVERIFY(m_xmlDb->metadata()->lastSelectedGroup() != nullptr);
|
||||
QCOMPARE(m_xmlDb->metadata()->lastSelectedGroup()->name(), QString("NewDatabase"));
|
||||
QVERIFY(m_xmlDb->metadata()->lastTopVisibleGroup() == m_xmlDb->metadata()->lastSelectedGroup());
|
||||
@@ -136,17 +136,18 @@ void TestKeePass2Format::testXmlGroupRoot()
|
||||
QCOMPARE(group->iconUuid(), QUuid());
|
||||
QVERIFY(group->isExpanded());
|
||||
TimeInfo ti = group->timeInfo();
|
||||
QCOMPARE(ti.lastModificationTime(), TestClock::datetimeUtc(2010, 8, 8, 17, 24, 27));
|
||||
QCOMPARE(ti.creationTime(), TestClock::datetimeUtc(2010, 8, 7, 17, 24, 27));
|
||||
QCOMPARE(ti.lastAccessTime(), TestClock::datetimeUtc(2010, 8, 9, 9, 9, 44));
|
||||
QCOMPARE(ti.expiryTime(), TestClock::datetimeUtc(2010, 8, 8, 17, 24, 17));
|
||||
QCOMPARE(ti.lastModificationTime(), MockClock::datetimeUtc(2010, 8, 8, 17, 24, 27));
|
||||
QCOMPARE(ti.creationTime(), MockClock::datetimeUtc(2010, 8, 7, 17, 24, 27));
|
||||
QCOMPARE(ti.lastAccessTime(), MockClock::datetimeUtc(2010, 8, 9, 9, 9, 44));
|
||||
QCOMPARE(ti.expiryTime(), MockClock::datetimeUtc(2010, 8, 8, 17, 24, 17));
|
||||
QVERIFY(!ti.expires());
|
||||
QCOMPARE(ti.usageCount(), 52);
|
||||
QCOMPARE(ti.locationChanged(), TestClock::datetimeUtc(2010, 8, 8, 17, 24, 27));
|
||||
QCOMPARE(ti.locationChanged(), MockClock::datetimeUtc(2010, 8, 8, 17, 24, 27));
|
||||
QCOMPARE(group->defaultAutoTypeSequence(), QString(""));
|
||||
QCOMPARE(group->autoTypeEnabled(), Group::Inherit);
|
||||
QCOMPARE(group->searchingEnabled(), Group::Inherit);
|
||||
QCOMPARE(group->lastTopVisibleEntry()->uuid(), QUuid::fromRfc4122(QByteArray::fromBase64("+wSUOv6qf0OzW8/ZHAs2sA==")));
|
||||
QCOMPARE(group->lastTopVisibleEntry()->uuid(),
|
||||
QUuid::fromRfc4122(QByteArray::fromBase64("+wSUOv6qf0OzW8/ZHAs2sA==")));
|
||||
QCOMPARE(group->children().size(), 3);
|
||||
QVERIFY(m_xmlDb->metadata()->recycleBin() == m_xmlDb->rootGroup()->children().at(2));
|
||||
|
||||
@@ -203,13 +204,13 @@ void TestKeePass2Format::testXmlEntry1()
|
||||
QCOMPARE(entry->tags(), QString("a b c"));
|
||||
|
||||
const TimeInfo ti = entry->timeInfo();
|
||||
QCOMPARE(ti.lastModificationTime(), TestClock::datetimeUtc(2010, 8, 25, 16, 19, 25));
|
||||
QCOMPARE(ti.creationTime(), TestClock::datetimeUtc(2010, 8, 25, 16, 13, 54));
|
||||
QCOMPARE(ti.lastAccessTime(), TestClock::datetimeUtc(2010, 8, 25, 16, 19, 25));
|
||||
QCOMPARE(ti.expiryTime(), TestClock::datetimeUtc(2010, 8, 25, 16, 12, 57));
|
||||
QCOMPARE(ti.lastModificationTime(), MockClock::datetimeUtc(2010, 8, 25, 16, 19, 25));
|
||||
QCOMPARE(ti.creationTime(), MockClock::datetimeUtc(2010, 8, 25, 16, 13, 54));
|
||||
QCOMPARE(ti.lastAccessTime(), MockClock::datetimeUtc(2010, 8, 25, 16, 19, 25));
|
||||
QCOMPARE(ti.expiryTime(), MockClock::datetimeUtc(2010, 8, 25, 16, 12, 57));
|
||||
QVERIFY(!ti.expires());
|
||||
QCOMPARE(ti.usageCount(), 8);
|
||||
QCOMPARE(ti.locationChanged(), TestClock::datetimeUtc(2010, 8, 25, 16, 13, 54));
|
||||
QCOMPARE(ti.locationChanged(), MockClock::datetimeUtc(2010, 8, 25, 16, 13, 54));
|
||||
|
||||
QList<QString> attrs = entry->attributes()->keys();
|
||||
QCOMPARE(entry->attributes()->value("Notes"), QString("Notes"));
|
||||
@@ -308,7 +309,7 @@ void TestKeePass2Format::testXmlEntryHistory()
|
||||
const Entry* entry = entryMain->historyItems().at(0);
|
||||
QCOMPARE(entry->uuid(), entryMain->uuid());
|
||||
QVERIFY(!entry->parent());
|
||||
QCOMPARE(entry->timeInfo().lastModificationTime(), TestClock::datetimeUtc(2010, 8, 25, 16, 13, 54));
|
||||
QCOMPARE(entry->timeInfo().lastModificationTime(), MockClock::datetimeUtc(2010, 8, 25, 16, 13, 54));
|
||||
QCOMPARE(entry->timeInfo().usageCount(), 3);
|
||||
QCOMPARE(entry->title(), QString("Sample Entry"));
|
||||
QCOMPARE(entry->url(), QString("http://www.somesite.com/"));
|
||||
@@ -318,7 +319,7 @@ void TestKeePass2Format::testXmlEntryHistory()
|
||||
const Entry* entry = entryMain->historyItems().at(1);
|
||||
QCOMPARE(entry->uuid(), entryMain->uuid());
|
||||
QVERIFY(!entry->parent());
|
||||
QCOMPARE(entry->timeInfo().lastModificationTime(), TestClock::datetimeUtc(2010, 8, 25, 16, 15, 43));
|
||||
QCOMPARE(entry->timeInfo().lastModificationTime(), MockClock::datetimeUtc(2010, 8, 25, 16, 15, 43));
|
||||
QCOMPARE(entry->timeInfo().usageCount(), 7);
|
||||
QCOMPARE(entry->title(), QString("Sample Entry 1"));
|
||||
QCOMPARE(entry->url(), QString("http://www.somesite.com/"));
|
||||
@@ -332,11 +333,11 @@ void TestKeePass2Format::testXmlDeletedObjects()
|
||||
|
||||
delObj = objList.takeFirst();
|
||||
QCOMPARE(delObj.uuid, QUuid::fromRfc4122(QByteArray::fromBase64("5K/bzWCSmkCv5OZxYl4N/w==")));
|
||||
QCOMPARE(delObj.deletionTime, TestClock::datetimeUtc(2010, 8, 25, 16, 14, 12));
|
||||
QCOMPARE(delObj.deletionTime, MockClock::datetimeUtc(2010, 8, 25, 16, 14, 12));
|
||||
|
||||
delObj = objList.takeFirst();
|
||||
QCOMPARE(delObj.uuid, QUuid::fromRfc4122(QByteArray::fromBase64("80h8uSNWgkKhKCp1TgXF7g==")));
|
||||
QCOMPARE(delObj.deletionTime, TestClock::datetimeUtc(2010, 8, 25, 16, 14, 14));
|
||||
QCOMPARE(delObj.deletionTime, MockClock::datetimeUtc(2010, 8, 25, 16, 14, 14));
|
||||
|
||||
QVERIFY(objList.isEmpty());
|
||||
}
|
||||
@@ -351,7 +352,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 +393,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 +447,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 +475,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 +504,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 +550,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 +571,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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
@@ -226,7 +227,7 @@ void TestKeys::testCompositeKeyComponents()
|
||||
auto fileKeyEnc = QSharedPointer<FileKey>::create();
|
||||
QString error;
|
||||
fileKeyEnc->load(QString("%1/%2").arg(QString(KEEPASSX_TEST_DATA_DIR), "FileKeyHashed.key"), &error);
|
||||
if (!error.isNull()) {
|
||||
if (!error.isEmpty()) {
|
||||
QFAIL(qPrintable(error));
|
||||
}
|
||||
auto challengeResponseKeyEnc = QSharedPointer<MockChallengeResponseKey>::create(QByteArray(16, 0x10));
|
||||
@@ -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,20 +278,20 @@ 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();
|
||||
compositeKeyDec3->addKey(passwordKeyEnc);
|
||||
auto fileKeyWrong = QSharedPointer<FileKey>::create();
|
||||
fileKeyWrong->load(QString("%1/%2").arg(QString(KEEPASSX_TEST_DATA_DIR), "FileKeyHashed2.key"), &error);
|
||||
if (!error.isNull()) {
|
||||
if (!error.isEmpty()) {
|
||||
QFAIL(qPrintable(error));
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
|
||||
#include "TestMerge.h"
|
||||
#include "TestGlobal.h"
|
||||
#include "stub/TestClock.h"
|
||||
#include "mock/MockClock.h"
|
||||
|
||||
#include "core/Merger.h"
|
||||
#include "core/Metadata.h"
|
||||
#include "crypto/Crypto.h"
|
||||
|
||||
#include <QSignalSpy>
|
||||
|
||||
QTEST_GUILESS_MAIN(TestMerge)
|
||||
|
||||
namespace
|
||||
@@ -34,8 +36,8 @@ namespace
|
||||
return timeInfo;
|
||||
}
|
||||
|
||||
TestClock* m_clock = nullptr;
|
||||
}
|
||||
MockClock* m_clock = nullptr;
|
||||
} // namespace
|
||||
|
||||
void TestMerge::initTestCase()
|
||||
{
|
||||
@@ -47,13 +49,13 @@ void TestMerge::initTestCase()
|
||||
void TestMerge::init()
|
||||
{
|
||||
Q_ASSERT(m_clock == nullptr);
|
||||
m_clock = new TestClock(2010, 5, 5, 10, 30, 10);
|
||||
TestClock::setup(m_clock);
|
||||
m_clock = new MockClock(2010, 5, 5, 10, 30, 10);
|
||||
MockClock::setup(m_clock);
|
||||
}
|
||||
|
||||
void TestMerge::cleanup()
|
||||
{
|
||||
TestClock::teardown();
|
||||
MockClock::teardown();
|
||||
m_clock = nullptr;
|
||||
}
|
||||
|
||||
@@ -125,7 +127,7 @@ void TestMerge::testResolveConflictNewer()
|
||||
QVERIFY(groupDestinationInitial != nullptr);
|
||||
QCOMPARE(groupDestinationInitial->entries().size(), 2);
|
||||
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entrySourceInitial != nullptr);
|
||||
QVERIFY(entrySourceInitial->group() == groupSourceInitial);
|
||||
|
||||
@@ -159,7 +161,7 @@ void TestMerge::testResolveConflictNewer()
|
||||
QCOMPARE(groupDestinationMerged->entries().size(), 2);
|
||||
QCOMPARE(groupDestinationMerged->timeInfo(), groupDestinationInitialTimeInfo);
|
||||
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entryDestinationMerged != nullptr);
|
||||
QVERIFY(entryDestinationMerged->group() != nullptr);
|
||||
QCOMPARE(entryDestinationMerged->password(), QString("password"));
|
||||
@@ -192,7 +194,7 @@ void TestMerge::testResolveConflictExisting()
|
||||
QVERIFY(groupDestinationInitial != nullptr);
|
||||
QCOMPARE(groupSourceInitial->entries().size(), 2);
|
||||
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entrySourceInitial != nullptr);
|
||||
QVERIFY(entrySourceInitial->group() == groupSourceInitial);
|
||||
|
||||
@@ -213,7 +215,7 @@ void TestMerge::testResolveConflictExisting()
|
||||
QPointer<Group> groupDestinationUpdated = dbDestination->rootGroup()->findChildByName("group1");
|
||||
QVERIFY(groupDestinationUpdated != nullptr);
|
||||
QCOMPARE(groupDestinationUpdated->entries().size(), 2);
|
||||
QPointer<Entry> entryDestinationUpdated = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entryDestinationUpdated = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entryDestinationUpdated != nullptr);
|
||||
QVERIFY(entryDestinationUpdated->group() == groupDestinationUpdated);
|
||||
|
||||
@@ -244,7 +246,7 @@ void TestMerge::testResolveConflictExisting()
|
||||
QCOMPARE(groupDestinationMerged->entries().size(), 2);
|
||||
QCOMPARE(groupDestinationMerged->timeInfo(), groupDestinationUpdatedNewerTimeInfo);
|
||||
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entryDestinationMerged != nullptr);
|
||||
QCOMPARE(entryDestinationMerged->password(), QString("password2"));
|
||||
QCOMPARE(entryDestinationMerged->timeInfo(), entryDestinationUpdatedNewerTimeInfo);
|
||||
@@ -300,7 +302,9 @@ void TestMerge::testResolveConflictDuplicate()
|
||||
"KeepBoth should not reuse the UUIDs when cloning.");
|
||||
}
|
||||
|
||||
void TestMerge::testResolveConflictTemplate(int mergeMode, std::function<void(Database*, const QMap<const char*, QDateTime>&)> verification)
|
||||
void TestMerge::testResolveConflictTemplate(
|
||||
int mergeMode,
|
||||
std::function<void(Database*, const QMap<const char*, QDateTime>&)> verification)
|
||||
{
|
||||
QMap<const char*, QDateTime> timestamps;
|
||||
timestamps["initialTime"] = m_clock->currentDateTimeUtc();
|
||||
@@ -382,9 +386,9 @@ void TestMerge::testResolveConflictTemplate(int mergeMode, std::function<void(Da
|
||||
|
||||
m_clock->advanceMinute(1);
|
||||
|
||||
QPointer<Entry> deletedEntryDestination = dbDestination->rootGroup()->findEntry("deletedDestination");
|
||||
QPointer<Entry> deletedEntryDestination = dbDestination->rootGroup()->findEntryByPath("deletedDestination");
|
||||
dbDestination->recycleEntry(deletedEntryDestination);
|
||||
QPointer<Entry> deletedEntrySource = dbSource->rootGroup()->findEntry("deletedSource");
|
||||
QPointer<Entry> deletedEntrySource = dbSource->rootGroup()->findEntryByPath("deletedSource");
|
||||
dbSource->recycleEntry(deletedEntrySource);
|
||||
|
||||
m_clock->advanceMinute(1);
|
||||
@@ -428,11 +432,12 @@ void TestMerge::testResolveConflictTemplate(int mergeMode, std::function<void(Da
|
||||
|
||||
verification(dbDestination.data(), timestamps);
|
||||
|
||||
QVERIFY(dbDestination->rootGroup()->findEntry("entryDestination"));
|
||||
QVERIFY(dbDestination->rootGroup()->findEntry("entrySource"));
|
||||
QVERIFY(dbDestination->rootGroup()->findEntryByPath("entryDestination"));
|
||||
QVERIFY(dbDestination->rootGroup()->findEntryByPath("entrySource"));
|
||||
}
|
||||
|
||||
void TestMerge::testDeletionConflictTemplate(int mergeMode, std::function<void(Database*, const QMap<QString, QUuid>&)> verification)
|
||||
void TestMerge::testDeletionConflictTemplate(int mergeMode,
|
||||
std::function<void(Database*, const QMap<QString, QUuid>&)> verification)
|
||||
{
|
||||
QMap<QString, QUuid> identifiers;
|
||||
m_clock->currentDateTimeUtc();
|
||||
@@ -607,7 +612,7 @@ void TestMerge::assertDeletionNewerOnly(Database* db, const QMap<QString, QUuid>
|
||||
QVERIFY(db->containsDeletedObject(identifiers["EntryDeletedInTargetAfterEntryUpdatedInSource"]));
|
||||
}
|
||||
|
||||
void TestMerge::assertDeletionLocalOnly(Database* db, const QMap<QString, QUuid> &identifiers)
|
||||
void TestMerge::assertDeletionLocalOnly(Database* db, const QMap<QString, QUuid>& identifiers)
|
||||
{
|
||||
QPointer<Group> mergedRootGroup = db->rootGroup();
|
||||
|
||||
@@ -645,66 +650,80 @@ void TestMerge::assertDeletionLocalOnly(Database* db, const QMap<QString, QUuid>
|
||||
QVERIFY(db->containsDeletedObject(identifiers["EntryDeletedInTargetAfterEntryUpdatedInSource"]));
|
||||
}
|
||||
|
||||
void TestMerge::assertUpdateMergedEntry1(Entry *mergedEntry1, const QMap<const char *, QDateTime> ×tamps)
|
||||
void TestMerge::assertUpdateMergedEntry1(Entry* mergedEntry1, const QMap<const char*, QDateTime>& timestamps)
|
||||
{
|
||||
QCOMPARE(mergedEntry1->historyItems().count(), 4);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(0)->notes(), QString(""));
|
||||
QCOMPARE(mergedEntry1->historyItems().at(0)->timeInfo().lastModificationTime(), timestamps["initialTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(1)->notes(), QString(""));
|
||||
QCOMPARE(mergedEntry1->historyItems().at(1)->timeInfo().lastModificationTime(), timestamps["oldestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(1)->timeInfo().lastModificationTime(),
|
||||
timestamps["oldestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(2)->notes(), QString("1 Common"));
|
||||
QCOMPARE(mergedEntry1->historyItems().at(2)->timeInfo().lastModificationTime(), timestamps["newestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(2)->timeInfo().lastModificationTime(),
|
||||
timestamps["newestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(3)->notes(), QString("2 Source"));
|
||||
QCOMPARE(mergedEntry1->historyItems().at(3)->timeInfo().lastModificationTime(), timestamps["oldestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(3)->timeInfo().lastModificationTime(),
|
||||
timestamps["oldestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->notes(), QString("3 Destination"));
|
||||
QCOMPARE(mergedEntry1->timeInfo().lastModificationTime(), timestamps["newestDivergingHistoryTime"]);
|
||||
}
|
||||
|
||||
void TestMerge::assertUpdateReappliedEntry2(Entry *mergedEntry2, const QMap<const char *, QDateTime> ×tamps)
|
||||
void TestMerge::assertUpdateReappliedEntry2(Entry* mergedEntry2, const QMap<const char*, QDateTime>& timestamps)
|
||||
{
|
||||
QCOMPARE(mergedEntry2->historyItems().count(), 5);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(0)->notes(), QString(""));
|
||||
QCOMPARE(mergedEntry2->historyItems().at(0)->timeInfo().lastModificationTime(), timestamps["initialTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(1)->notes(), QString(""));
|
||||
QCOMPARE(mergedEntry2->historyItems().at(1)->timeInfo().lastModificationTime(), timestamps["oldestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(1)->timeInfo().lastModificationTime(),
|
||||
timestamps["oldestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(2)->notes(), QString("1 Common"));
|
||||
QCOMPARE(mergedEntry2->historyItems().at(2)->timeInfo().lastModificationTime(), timestamps["newestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(2)->timeInfo().lastModificationTime(),
|
||||
timestamps["newestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(3)->notes(), QString("2 Destination"));
|
||||
QCOMPARE(mergedEntry2->historyItems().at(3)->timeInfo().lastModificationTime(), timestamps["oldestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(3)->timeInfo().lastModificationTime(),
|
||||
timestamps["oldestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(4)->notes(), QString("3 Source"));
|
||||
QCOMPARE(mergedEntry2->historyItems().at(4)->timeInfo().lastModificationTime(), timestamps["newestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(4)->timeInfo().lastModificationTime(),
|
||||
timestamps["newestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->notes(), QString("2 Destination"));
|
||||
QCOMPARE(mergedEntry2->timeInfo().lastModificationTime(), timestamps["mergeTime"]);
|
||||
}
|
||||
|
||||
void TestMerge::assertUpdateReappliedEntry1(Entry *mergedEntry1, const QMap<const char *, QDateTime> ×tamps)
|
||||
void TestMerge::assertUpdateReappliedEntry1(Entry* mergedEntry1, const QMap<const char*, QDateTime>& timestamps)
|
||||
{
|
||||
QCOMPARE(mergedEntry1->historyItems().count(), 5);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(0)->notes(), QString(""));
|
||||
QCOMPARE(mergedEntry1->historyItems().at(0)->timeInfo().lastModificationTime(), timestamps["initialTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(1)->notes(), QString(""));
|
||||
QCOMPARE(mergedEntry1->historyItems().at(1)->timeInfo().lastModificationTime(), timestamps["oldestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(1)->timeInfo().lastModificationTime(),
|
||||
timestamps["oldestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(2)->notes(), QString("1 Common"));
|
||||
QCOMPARE(mergedEntry1->historyItems().at(2)->timeInfo().lastModificationTime(), timestamps["newestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(2)->timeInfo().lastModificationTime(),
|
||||
timestamps["newestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(3)->notes(), QString("2 Source"));
|
||||
QCOMPARE(mergedEntry1->historyItems().at(3)->timeInfo().lastModificationTime(), timestamps["oldestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(3)->timeInfo().lastModificationTime(),
|
||||
timestamps["oldestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(4)->notes(), QString("3 Destination"));
|
||||
QCOMPARE(mergedEntry1->historyItems().at(4)->timeInfo().lastModificationTime(), timestamps["newestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->historyItems().at(4)->timeInfo().lastModificationTime(),
|
||||
timestamps["newestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry1->notes(), QString("2 Source"));
|
||||
QCOMPARE(mergedEntry1->timeInfo().lastModificationTime(), timestamps["mergeTime"]);
|
||||
}
|
||||
|
||||
void TestMerge::assertUpdateMergedEntry2(Entry *mergedEntry2, const QMap<const char *, QDateTime> ×tamps)
|
||||
void TestMerge::assertUpdateMergedEntry2(Entry* mergedEntry2, const QMap<const char*, QDateTime>& timestamps)
|
||||
{
|
||||
QCOMPARE(mergedEntry2->historyItems().count(), 4);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(0)->notes(), QString(""));
|
||||
QCOMPARE(mergedEntry2->historyItems().at(0)->timeInfo().lastModificationTime(), timestamps["initialTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(1)->notes(), QString(""));
|
||||
QCOMPARE(mergedEntry2->historyItems().at(1)->timeInfo().lastModificationTime(), timestamps["oldestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(1)->timeInfo().lastModificationTime(),
|
||||
timestamps["oldestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(2)->notes(), QString("1 Common"));
|
||||
QCOMPARE(mergedEntry2->historyItems().at(2)->timeInfo().lastModificationTime(), timestamps["newestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(2)->timeInfo().lastModificationTime(),
|
||||
timestamps["newestCommonHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(3)->notes(), QString("2 Destination"));
|
||||
QCOMPARE(mergedEntry2->historyItems().at(3)->timeInfo().lastModificationTime(), timestamps["oldestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->historyItems().at(3)->timeInfo().lastModificationTime(),
|
||||
timestamps["oldestDivergingHistoryTime"]);
|
||||
QCOMPARE(mergedEntry2->notes(), QString("3 Source"));
|
||||
QCOMPARE(mergedEntry2->timeInfo().lastModificationTime(), timestamps["newestDivergingHistoryTime"]);
|
||||
}
|
||||
@@ -790,7 +809,7 @@ void TestMerge::testMoveEntry()
|
||||
QScopedPointer<Database> dbSource(
|
||||
createTestDatabaseStructureClone(dbDestination.data(), Entry::CloneNoFlags, Group::CloneIncludeEntries));
|
||||
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entrySourceInitial != nullptr);
|
||||
|
||||
QPointer<Group> groupSourceInitial = dbSource->rootGroup()->findChildByName("group2");
|
||||
@@ -807,7 +826,7 @@ void TestMerge::testMoveEntry()
|
||||
Merger merger(dbSource.data(), dbDestination.data());
|
||||
merger.merge();
|
||||
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entryDestinationMerged != nullptr);
|
||||
QCOMPARE(entryDestinationMerged->group()->name(), QString("group2"));
|
||||
QCOMPARE(dbDestination->rootGroup()->entriesRecursive().size(), 2);
|
||||
@@ -824,7 +843,7 @@ void TestMerge::testMoveEntryPreserveChanges()
|
||||
QScopedPointer<Database> dbSource(
|
||||
createTestDatabaseStructureClone(dbDestination.data(), Entry::CloneNoFlags, Group::CloneIncludeEntries));
|
||||
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entrySourceInitial != nullptr);
|
||||
|
||||
QPointer<Group> group2Source = dbSource->rootGroup()->findChildByName("group2");
|
||||
@@ -835,7 +854,7 @@ void TestMerge::testMoveEntryPreserveChanges()
|
||||
entrySourceInitial->setGroup(group2Source);
|
||||
QCOMPARE(entrySourceInitial->group()->name(), QString("group2"));
|
||||
|
||||
QPointer<Entry> entryDestinationInitial = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entryDestinationInitial = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entryDestinationInitial != nullptr);
|
||||
|
||||
m_clock->advanceSecond(1);
|
||||
@@ -849,7 +868,7 @@ void TestMerge::testMoveEntryPreserveChanges()
|
||||
Merger merger(dbSource.data(), dbDestination.data());
|
||||
merger.merge();
|
||||
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entryDestinationMerged != nullptr);
|
||||
QCOMPARE(entryDestinationMerged->group()->name(), QString("group2"));
|
||||
QCOMPARE(dbDestination->rootGroup()->entriesRecursive().size(), 2);
|
||||
@@ -892,7 +911,7 @@ void TestMerge::testMoveEntryIntoNewGroup()
|
||||
groupSourceCreated->setUuid(QUuid::createUuid());
|
||||
groupSourceCreated->setParent(dbSource->rootGroup());
|
||||
|
||||
QPointer<Entry> entrySourceMoved = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entrySourceMoved = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
entrySourceMoved->setGroup(groupSourceCreated);
|
||||
|
||||
m_clock->advanceSecond(1);
|
||||
@@ -907,7 +926,7 @@ void TestMerge::testMoveEntryIntoNewGroup()
|
||||
QCOMPARE(groupDestinationMerged->name(), QString("group3"));
|
||||
QCOMPARE(groupDestinationMerged->entries().size(), 1);
|
||||
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entryDestinationMerged != nullptr);
|
||||
QCOMPARE(entryDestinationMerged->group()->name(), QString("group3"));
|
||||
}
|
||||
@@ -929,7 +948,7 @@ void TestMerge::testUpdateEntryDifferentLocation()
|
||||
|
||||
m_clock->advanceSecond(1);
|
||||
|
||||
QPointer<Entry> entryDestinationMoved = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entryDestinationMoved = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entryDestinationMoved != nullptr);
|
||||
entryDestinationMoved->setGroup(groupDestinationCreated);
|
||||
QUuid uuidBeforeSyncing = entryDestinationMoved->uuid();
|
||||
@@ -938,7 +957,7 @@ void TestMerge::testUpdateEntryDifferentLocation()
|
||||
// Change the entry in the source db.
|
||||
m_clock->advanceSecond(1);
|
||||
|
||||
QPointer<Entry> entrySourceMoved = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entrySourceMoved = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entrySourceMoved != nullptr);
|
||||
entrySourceMoved->beginUpdate();
|
||||
entrySourceMoved->setUsername("username");
|
||||
@@ -954,7 +973,7 @@ void TestMerge::testUpdateEntryDifferentLocation()
|
||||
|
||||
QCOMPARE(dbDestination->rootGroup()->entriesRecursive().size(), 2);
|
||||
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entryDestinationMerged != nullptr);
|
||||
QVERIFY(entryDestinationMerged->group() != nullptr);
|
||||
QCOMPARE(entryDestinationMerged->username(), QString("username"));
|
||||
@@ -983,7 +1002,7 @@ void TestMerge::testUpdateGroup()
|
||||
dbSource->metadata()->addCustomIcon(customIconId, customIcon);
|
||||
groupSourceInitial->setIcon(customIconId);
|
||||
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entrySourceInitial != nullptr);
|
||||
entrySourceInitial->setGroup(groupSourceInitial);
|
||||
entrySourceInitial->setTitle("entry1 renamed");
|
||||
@@ -996,7 +1015,7 @@ void TestMerge::testUpdateGroup()
|
||||
|
||||
QCOMPARE(dbDestination->rootGroup()->entriesRecursive().size(), 2);
|
||||
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntry("entry1 renamed");
|
||||
QPointer<Entry> entryDestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1 renamed");
|
||||
QVERIFY(entryDestinationMerged != nullptr);
|
||||
QVERIFY(entryDestinationMerged->group() != nullptr);
|
||||
QCOMPARE(entryDestinationMerged->group()->name(), QString("group2 renamed"));
|
||||
@@ -1125,7 +1144,7 @@ void TestMerge::testDeletedEntry()
|
||||
|
||||
m_clock->advanceSecond(1);
|
||||
|
||||
QPointer<Entry> entry1SourceInitial = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entry1SourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entry1SourceInitial != nullptr);
|
||||
QUuid entry1Uuid = entry1SourceInitial->uuid();
|
||||
delete entry1SourceInitial;
|
||||
@@ -1133,7 +1152,7 @@ void TestMerge::testDeletedEntry()
|
||||
|
||||
m_clock->advanceSecond(1);
|
||||
|
||||
QPointer<Entry> entry2DestinationInitial = dbDestination->rootGroup()->findEntry("entry2");
|
||||
QPointer<Entry> entry2DestinationInitial = dbDestination->rootGroup()->findEntryByPath("entry2");
|
||||
QVERIFY(entry2DestinationInitial != nullptr);
|
||||
QUuid entry2Uuid = entry2DestinationInitial->uuid();
|
||||
delete entry2DestinationInitial;
|
||||
@@ -1144,10 +1163,10 @@ void TestMerge::testDeletedEntry()
|
||||
Merger merger(dbSource.data(), dbDestination.data());
|
||||
merger.merge();
|
||||
|
||||
QPointer<Entry> entry1DestinationMerged = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entry1DestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entry1DestinationMerged);
|
||||
QVERIFY(!dbDestination->containsDeletedObject(entry1Uuid));
|
||||
QPointer<Entry> entry2DestinationMerged = dbDestination->rootGroup()->findEntry("entry2");
|
||||
QPointer<Entry> entry2DestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry2");
|
||||
QVERIFY(entry2DestinationMerged);
|
||||
// Uuid in db and deletedObjects is intended according to KeePass #1752
|
||||
QVERIFY(dbDestination->containsDeletedObject(entry2Uuid));
|
||||
@@ -1176,9 +1195,9 @@ void TestMerge::testDeletedGroup()
|
||||
|
||||
QPointer<Group> group1SourceInitial = dbSource->rootGroup()->findChildByName("group1");
|
||||
QVERIFY(group1SourceInitial != nullptr);
|
||||
QPointer<Entry> entry1SourceInitial = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entry1SourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entry1SourceInitial != nullptr);
|
||||
QPointer<Entry> entry2SourceInitial = dbSource->rootGroup()->findEntry("entry2");
|
||||
QPointer<Entry> entry2SourceInitial = dbSource->rootGroup()->findEntryByPath("entry2");
|
||||
QVERIFY(entry2SourceInitial != nullptr);
|
||||
QUuid group1Uuid = group1SourceInitial->uuid();
|
||||
QUuid entry1Uuid = entry1SourceInitial->uuid();
|
||||
@@ -1206,11 +1225,11 @@ void TestMerge::testDeletedGroup()
|
||||
QVERIFY(!dbDestination->containsDeletedObject(entry2Uuid));
|
||||
QVERIFY(!dbDestination->containsDeletedObject(group2Uuid));
|
||||
|
||||
QPointer<Entry> entry1DestinationMerged = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entry1DestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entry1DestinationMerged);
|
||||
QPointer<Entry> entry2DestinationMerged = dbDestination->rootGroup()->findEntry("entry2");
|
||||
QPointer<Entry> entry2DestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry2");
|
||||
QVERIFY(entry2DestinationMerged);
|
||||
QPointer<Entry> entry3DestinationMerged = dbDestination->rootGroup()->findEntry("entry3");
|
||||
QPointer<Entry> entry3DestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry3");
|
||||
QVERIFY(entry3DestinationMerged);
|
||||
QPointer<Group> group1DestinationMerged = dbDestination->rootGroup()->findChildByName("group1");
|
||||
QVERIFY(group1DestinationMerged);
|
||||
@@ -1228,7 +1247,7 @@ void TestMerge::testDeletedRevertedEntry()
|
||||
|
||||
m_clock->advanceSecond(1);
|
||||
|
||||
QPointer<Entry> entry1DestinationInitial = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entry1DestinationInitial = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entry1DestinationInitial != nullptr);
|
||||
QUuid entry1Uuid = entry1DestinationInitial->uuid();
|
||||
delete entry1DestinationInitial;
|
||||
@@ -1236,7 +1255,7 @@ void TestMerge::testDeletedRevertedEntry()
|
||||
|
||||
m_clock->advanceSecond(1);
|
||||
|
||||
QPointer<Entry> entry2SourceInitial = dbSource->rootGroup()->findEntry("entry2");
|
||||
QPointer<Entry> entry2SourceInitial = dbSource->rootGroup()->findEntryByPath("entry2");
|
||||
QVERIFY(entry2SourceInitial != nullptr);
|
||||
QUuid entry2Uuid = entry2SourceInitial->uuid();
|
||||
delete entry2SourceInitial;
|
||||
@@ -1244,11 +1263,11 @@ void TestMerge::testDeletedRevertedEntry()
|
||||
|
||||
m_clock->advanceSecond(1);
|
||||
|
||||
QPointer<Entry> entry1SourceInitial = dbSource->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entry1SourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entry1SourceInitial != nullptr);
|
||||
entry1SourceInitial->setNotes("Updated");
|
||||
|
||||
QPointer<Entry> entry2DestinationInitial = dbDestination->rootGroup()->findEntry("entry2");
|
||||
QPointer<Entry> entry2DestinationInitial = dbDestination->rootGroup()->findEntryByPath("entry2");
|
||||
QVERIFY(entry2DestinationInitial != nullptr);
|
||||
entry2DestinationInitial->setNotes("Updated");
|
||||
|
||||
@@ -1259,10 +1278,10 @@ void TestMerge::testDeletedRevertedEntry()
|
||||
QVERIFY(dbDestination->containsDeletedObject(entry1Uuid));
|
||||
QVERIFY(!dbDestination->containsDeletedObject(entry2Uuid));
|
||||
|
||||
QPointer<Entry> entry1DestinationMerged = dbDestination->rootGroup()->findEntry("entry1");
|
||||
QPointer<Entry> entry1DestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry1");
|
||||
QVERIFY(entry1DestinationMerged);
|
||||
QVERIFY(entry1DestinationMerged->notes() == "Updated");
|
||||
QPointer<Entry> entry2DestinationMerged = dbDestination->rootGroup()->findEntry("entry2");
|
||||
QPointer<Entry> entry2DestinationMerged = dbDestination->rootGroup()->findEntryByPath("entry2");
|
||||
QVERIFY(entry2DestinationMerged);
|
||||
QVERIFY(entry2DestinationMerged->notes() == "Updated");
|
||||
}
|
||||
@@ -1355,6 +1374,37 @@ void TestMerge::testResolveGroupConflictOlder()
|
||||
QVERIFY(groupDestinationMerged != nullptr);
|
||||
}
|
||||
|
||||
void TestMerge::testMergeNotModified()
|
||||
{
|
||||
QScopedPointer<Database> dbDestination(createTestDatabase());
|
||||
QScopedPointer<Database> dbSource(
|
||||
createTestDatabaseStructureClone(dbDestination.data(), Entry::CloneNoFlags, Group::CloneIncludeEntries));
|
||||
|
||||
QSignalSpy modifiedSignalSpy(dbDestination.data(), SIGNAL(databaseModified()));
|
||||
Merger merger(dbSource.data(), dbDestination.data());
|
||||
merger.merge();
|
||||
QTRY_VERIFY(modifiedSignalSpy.empty());
|
||||
}
|
||||
|
||||
void TestMerge::testMergeModified()
|
||||
{
|
||||
QScopedPointer<Database> dbDestination(createTestDatabase());
|
||||
QScopedPointer<Database> dbSource(
|
||||
createTestDatabaseStructureClone(dbDestination.data(), Entry::CloneNoFlags, Group::CloneIncludeEntries));
|
||||
|
||||
QSignalSpy modifiedSignalSpy(dbDestination.data(), SIGNAL(databaseModified()));
|
||||
// Make sure the two changes have a different timestamp.
|
||||
QTest::qSleep(1);
|
||||
Entry* entry = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||
entry->beginUpdate();
|
||||
entry->setTitle("new title");
|
||||
entry->endUpdate();
|
||||
|
||||
Merger merger(dbSource.data(), dbDestination.data());
|
||||
merger.merge();
|
||||
QTRY_VERIFY(!modifiedSignalSpy.empty());
|
||||
}
|
||||
|
||||
Database* TestMerge::createTestDatabase()
|
||||
{
|
||||
Database* db = new Database();
|
||||
|
||||
@@ -36,6 +36,8 @@ private slots:
|
||||
void testResolveConflictNewer();
|
||||
void testResolveConflictExisting();
|
||||
void testResolveGroupConflictOlder();
|
||||
void testMergeNotModified();
|
||||
void testMergeModified();
|
||||
void testResolveConflictDuplicate();
|
||||
void testResolveConflictEntry_Synchronize();
|
||||
void testResolveConflictEntry_KeepLocal();
|
||||
@@ -64,15 +66,16 @@ private slots:
|
||||
private:
|
||||
Database* createTestDatabase();
|
||||
Database* createTestDatabaseStructureClone(Database* source, int entryFlags, int groupFlags);
|
||||
void testResolveConflictTemplate(int mergeMode, std::function<void(Database*, const QMap<const char*, QDateTime>&)> verification);
|
||||
void testDeletionConflictTemplate(int mergeMode, std::function<void(Database*, const QMap<QString, QUuid>&)> verification);
|
||||
static void assertDeletionNewerOnly(Database *db, const QMap<QString, QUuid> &identifiers);
|
||||
static void assertDeletionLocalOnly(Database *db, const QMap<QString, QUuid> &identifiers);
|
||||
static void assertUpdateMergedEntry1(Entry *entry, const QMap<const char*, QDateTime> ×tamps);
|
||||
static void assertUpdateReappliedEntry2(Entry *entry, const QMap<const char*, QDateTime> ×tamps);
|
||||
static void assertUpdateReappliedEntry1(Entry *entry, const QMap<const char*, QDateTime> ×tamps);
|
||||
static void assertUpdateMergedEntry2(Entry *entry, const QMap<const char *, QDateTime> ×tamps);
|
||||
|
||||
void testResolveConflictTemplate(int mergeMode,
|
||||
std::function<void(Database*, const QMap<const char*, QDateTime>&)> verification);
|
||||
void testDeletionConflictTemplate(int mergeMode,
|
||||
std::function<void(Database*, const QMap<QString, QUuid>&)> verification);
|
||||
static void assertDeletionNewerOnly(Database* db, const QMap<QString, QUuid>& identifiers);
|
||||
static void assertDeletionLocalOnly(Database* db, const QMap<QString, QUuid>& identifiers);
|
||||
static void assertUpdateMergedEntry1(Entry* entry, const QMap<const char*, QDateTime>& timestamps);
|
||||
static void assertUpdateReappliedEntry2(Entry* entry, const QMap<const char*, QDateTime>& timestamps);
|
||||
static void assertUpdateReappliedEntry1(Entry* entry, const QMap<const char*, QDateTime>& timestamps);
|
||||
static void assertUpdateMergedEntry2(Entry* entry, const QMap<const char*, QDateTime>& timestamps);
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_TESTMERGE_H
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "TestModified.h"
|
||||
#include "stub/TestClock.h"
|
||||
#include "mock/MockClock.h"
|
||||
|
||||
#include <QSignalSpy>
|
||||
#include <QTest>
|
||||
@@ -31,7 +31,7 @@ QTEST_GUILESS_MAIN(TestModified)
|
||||
|
||||
namespace
|
||||
{
|
||||
TestClock* m_clock = nullptr;
|
||||
MockClock* m_clock = nullptr;
|
||||
}
|
||||
|
||||
void TestModified::initTestCase()
|
||||
@@ -42,13 +42,13 @@ void TestModified::initTestCase()
|
||||
void TestModified::init()
|
||||
{
|
||||
Q_ASSERT(m_clock == nullptr);
|
||||
m_clock = new TestClock(2010, 5, 5, 10, 30, 10);
|
||||
TestClock::setup(m_clock);
|
||||
m_clock = new MockClock(2010, 5, 5, 10, 30, 10);
|
||||
MockClock::setup(m_clock);
|
||||
}
|
||||
|
||||
void TestModified::cleanup()
|
||||
{
|
||||
TestClock::teardown();
|
||||
MockClock::teardown();
|
||||
m_clock = nullptr;
|
||||
}
|
||||
|
||||
@@ -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,67 @@ 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 +223,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 +647,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);
|
||||
}
|
||||
|
||||
@@ -90,38 +90,36 @@ void TestOpenSSHKey::testParseDSA()
|
||||
|
||||
void TestOpenSSHKey::testDecryptRSAAES128CBC()
|
||||
{
|
||||
const QString keyString = QString(
|
||||
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"Proc-Type: 4,ENCRYPTED\n"
|
||||
"DEK-Info: AES-128-CBC,804E4D214D1263FF94E3743FE799DBB4\n"
|
||||
"\n"
|
||||
"lM9TDfOTbiRhaGGDh7Hn+rqw8CCWcYBZYu7smyYLdnWKXKPmbne8CQFZBAS1FJwZ\n"
|
||||
"6Mj6n075yFGyzN9/OfeqKiUA4adlbwLbGwB+yyKsC2FlsvRIEr4hup02WWM47vHj\n"
|
||||
"DS4TRmNkE7MKFLhpNCyt5OGGM45s+/lwVTw51K0Hm99TBd72IrX4jfY9ZxAVbL3l\n"
|
||||
"aTohL8x6oOTe7q318QgJoFi+DjJhDWLGLLJ7fBqD2imz2fmrY4j8Jpw2sDe1rj82\n"
|
||||
"gMqqNG3FrfN0S4uYlWYH5pAh+BUcB1UdmTU/rV5wJMK1oUytmZv/J2+X/0k3Y93F\n"
|
||||
"aw6JWOy28OizW+TQXvv8gREWsp5PEclqUZhhGQbVbCQCiDOxg+xiXNySdRH1IqjR\n"
|
||||
"zQiKgD4SPzkxQekExPaIQT/KutWZdMNYybEqooCx8YyeDoN31z7Wa2rv6OulOn/j\n"
|
||||
"wJFvyd2PT/6brHKI4ky8RYroDf4FbVYKfyEW5CSAg2OyL/tY/kSPgy/k0WT7fDwq\n"
|
||||
"dPSuYM9yeWNL6kAhDqDOv8+s3xvOVEljktBvQvItQwVLmHszC3E2AcnaxzdblKPu\n"
|
||||
"e3+mBT80NXHjERK2ht+/9JYseK1ujNbNAaG8SbKfU3FF0VlyJ0QW6TuIEdpNnymT\n"
|
||||
"0fm0cDfKNaoeJIFnBRZhgIOJAic9DM0cTe/vSG69DaUYsaQPp36al7Fbux3GpFHS\n"
|
||||
"OtJEySYGro/6zvJ9dDIEfIGZjA3RaMt6+DuyJZXQdT2RNXa9j60xW7dXh0En4n82\n"
|
||||
"JUKTxYhDPLS5c8BzpJqoopxpKwElmrJ7Y3xpd6z2vIlD8ftuZrkk6siTMNQ2s7MI\n"
|
||||
"Xl332O+0H4k7uSfczHPOOw36TFhNjGQAP0b7O+0/RVG0ttOIoAn7ZkX3nfdbtG5B\n"
|
||||
"DWKvDaopvrcC2/scQ5uLUnqnBiGw1XiYpdg5ang7knHNzHZAIekVaYYZigpCAKp+\n"
|
||||
"OtoaDeUEzqFhYVmF8ad1fgvC9ZUsuxS4XUHCKl0H6CJcvW9MJPVbveqYoK+j9qKd\n"
|
||||
"iMIkQBP1kE2rzGZVGUkZTpM9LVD9nP0nsbr6E8BatFcNgRirsg2BTJglNpXlCmY6\n"
|
||||
"ldzJ/ELBbzoXIn+0wTGai0o4eBPx55baef69JfPuZqEB9pLNE+mHstrqIwcfqYu4\n"
|
||||
"M+Vzun1QshRMj9a1PVkIHfs1fLeebI4QCHO0vJlc9K4iYPM4rsDNO3YaAgGRuARS\n"
|
||||
"f3McGiGFxkv5zxe8i05ZBnn+exE77jpRKxd223jAMe2wu4WiFB7ZVo4Db6b5Oo2T\n"
|
||||
"TPh3VuY7TNMEKkcUi+mGLKjroocQ5j8WQYlfnyOaTalUVQDzOTNb67QIIoiszR0U\n"
|
||||
"+AXGyxHj0QtotZFoPME+AbS9Zqy3SgSOuIzPBPU5zS4uoKNdD5NPE5YAuafCjsDy\n"
|
||||
"MT4DVy+cPOQYUK022S7T2nsA1btmvUvD5LL2Mc8VuKsWOn/7FKZua6OCfipt6oX0\n"
|
||||
"1tzYrw0/ALK+CIdVdYIiPPfxGZkr+JSLOOg7u50tpmen9GzxgNTv63miygwUAIDF\n"
|
||||
"u0GbQwOueoA453/N75FcXOgrbqTdivyadUbRP+l7YJk/SfIytyJMOigejp+Z1lzF\n"
|
||||
"-----END RSA PRIVATE KEY-----\n"
|
||||
);
|
||||
const QString keyString = QString("-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"Proc-Type: 4,ENCRYPTED\n"
|
||||
"DEK-Info: AES-128-CBC,804E4D214D1263FF94E3743FE799DBB4\n"
|
||||
"\n"
|
||||
"lM9TDfOTbiRhaGGDh7Hn+rqw8CCWcYBZYu7smyYLdnWKXKPmbne8CQFZBAS1FJwZ\n"
|
||||
"6Mj6n075yFGyzN9/OfeqKiUA4adlbwLbGwB+yyKsC2FlsvRIEr4hup02WWM47vHj\n"
|
||||
"DS4TRmNkE7MKFLhpNCyt5OGGM45s+/lwVTw51K0Hm99TBd72IrX4jfY9ZxAVbL3l\n"
|
||||
"aTohL8x6oOTe7q318QgJoFi+DjJhDWLGLLJ7fBqD2imz2fmrY4j8Jpw2sDe1rj82\n"
|
||||
"gMqqNG3FrfN0S4uYlWYH5pAh+BUcB1UdmTU/rV5wJMK1oUytmZv/J2+X/0k3Y93F\n"
|
||||
"aw6JWOy28OizW+TQXvv8gREWsp5PEclqUZhhGQbVbCQCiDOxg+xiXNySdRH1IqjR\n"
|
||||
"zQiKgD4SPzkxQekExPaIQT/KutWZdMNYybEqooCx8YyeDoN31z7Wa2rv6OulOn/j\n"
|
||||
"wJFvyd2PT/6brHKI4ky8RYroDf4FbVYKfyEW5CSAg2OyL/tY/kSPgy/k0WT7fDwq\n"
|
||||
"dPSuYM9yeWNL6kAhDqDOv8+s3xvOVEljktBvQvItQwVLmHszC3E2AcnaxzdblKPu\n"
|
||||
"e3+mBT80NXHjERK2ht+/9JYseK1ujNbNAaG8SbKfU3FF0VlyJ0QW6TuIEdpNnymT\n"
|
||||
"0fm0cDfKNaoeJIFnBRZhgIOJAic9DM0cTe/vSG69DaUYsaQPp36al7Fbux3GpFHS\n"
|
||||
"OtJEySYGro/6zvJ9dDIEfIGZjA3RaMt6+DuyJZXQdT2RNXa9j60xW7dXh0En4n82\n"
|
||||
"JUKTxYhDPLS5c8BzpJqoopxpKwElmrJ7Y3xpd6z2vIlD8ftuZrkk6siTMNQ2s7MI\n"
|
||||
"Xl332O+0H4k7uSfczHPOOw36TFhNjGQAP0b7O+0/RVG0ttOIoAn7ZkX3nfdbtG5B\n"
|
||||
"DWKvDaopvrcC2/scQ5uLUnqnBiGw1XiYpdg5ang7knHNzHZAIekVaYYZigpCAKp+\n"
|
||||
"OtoaDeUEzqFhYVmF8ad1fgvC9ZUsuxS4XUHCKl0H6CJcvW9MJPVbveqYoK+j9qKd\n"
|
||||
"iMIkQBP1kE2rzGZVGUkZTpM9LVD9nP0nsbr6E8BatFcNgRirsg2BTJglNpXlCmY6\n"
|
||||
"ldzJ/ELBbzoXIn+0wTGai0o4eBPx55baef69JfPuZqEB9pLNE+mHstrqIwcfqYu4\n"
|
||||
"M+Vzun1QshRMj9a1PVkIHfs1fLeebI4QCHO0vJlc9K4iYPM4rsDNO3YaAgGRuARS\n"
|
||||
"f3McGiGFxkv5zxe8i05ZBnn+exE77jpRKxd223jAMe2wu4WiFB7ZVo4Db6b5Oo2T\n"
|
||||
"TPh3VuY7TNMEKkcUi+mGLKjroocQ5j8WQYlfnyOaTalUVQDzOTNb67QIIoiszR0U\n"
|
||||
"+AXGyxHj0QtotZFoPME+AbS9Zqy3SgSOuIzPBPU5zS4uoKNdD5NPE5YAuafCjsDy\n"
|
||||
"MT4DVy+cPOQYUK022S7T2nsA1btmvUvD5LL2Mc8VuKsWOn/7FKZua6OCfipt6oX0\n"
|
||||
"1tzYrw0/ALK+CIdVdYIiPPfxGZkr+JSLOOg7u50tpmen9GzxgNTv63miygwUAIDF\n"
|
||||
"u0GbQwOueoA453/N75FcXOgrbqTdivyadUbRP+l7YJk/SfIytyJMOigejp+Z1lzF\n"
|
||||
"-----END RSA PRIVATE KEY-----\n");
|
||||
|
||||
const QByteArray keyData = keyString.toLatin1();
|
||||
|
||||
@@ -180,65 +178,61 @@ void TestOpenSSHKey::testParseRSA()
|
||||
|
||||
void TestOpenSSHKey::testParseRSACompare()
|
||||
{
|
||||
const QString oldKeyString = QString(
|
||||
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"MIIEpAIBAAKCAQEAsCHtJicDPWnvHSIKbnTZaJkIB9vgE0pmLdK580JUqBuonVbB\n"
|
||||
"y1QTy0ZQ7/TtqvLPgwPK88TR46OLO/QGCzo2+XxgJ85uy0xfuyUYRmSuw0drsErN\n"
|
||||
"mH8vU91lSBxsGDp9LtBbgHKoR23vMWZ34IxFRc55XphrIH48ijsMaL6bXBwF/3tD\n"
|
||||
"9T3lm2MpP1huyVNnIY9+GRRWCy4f9LMj/UGu/n4RtwwfpOZBBRwYkq5QkzA9lPm/\n"
|
||||
"VzF3MP1rKTMkvAw+Nfb383mkmc6MRnsa6uh6iDa9aVB7naegM13UJQX/PY1Ks6pO\n"
|
||||
"XDpy/MQ7iCh+HmYNq5dRmARyaNl9xIXJNhz1cQIDAQABAoIBAQCnEUc1LUQxeM5K\n"
|
||||
"wANNCqE+SgoIClPdeHC7fmrLh1ttqe6ib6ybBUFRS31yXs0hnfefunVEDKlaV8K2\n"
|
||||
"N52UAMAsngFHQNRvGh6kEWeZPd9Xc+N98TZbNCjcT+DGKc+Om8wqH5DrodZlCq4c\n"
|
||||
"GaoT4HnE4TjWtZTH2XXrWF9I66PKFWf070R44nvyVcvaZi4pC2YmURRPuGF6K1iK\n"
|
||||
"dH8zM6HHG1UGu2W6hLNn+K01IulG0Lb8eWNaNYMmtQWaxyp7I2IWkkecUs3nCuiR\n"
|
||||
"byFOoomCjdh8r9yZFvwxjGUhgtkALN9GCU0Mwve+s11IB2gevruN+q9/Qejbyfdm\n"
|
||||
"IlgLAeTRAoGBANRcVzW9CYeobCf+U9hKJFEOur8XO+J2mTMaELA0EjWpTJFAeIT7\n"
|
||||
"KeRpCRG4/vOSklxxRF6vP1EACA4Z+5BlN+FTipHHs+bSEgqkPZiiANDH7Zot5Iqv\n"
|
||||
"1q0fRyldNRZNZK7DWp08BPNVWGA/EnEuKJiURxnxBaxNXbUyMCdjxvMvAoGBANRT\n"
|
||||
"utbrqS/bAa/DcHKn3V6DRqBl3TDOfvCNjiKC84a67F2uXgzLIdMktr4d1NyCZVJd\n"
|
||||
"7/zVgWORLIdg1eAi6rYGoOvNV39wwga7CF+m9sBY0wAaKYCELe6L26r4aQHVCX6n\n"
|
||||
"rnIgUv+4o4itmU2iP0r3wlmDC9pDRQP82vfvQPlfAoGASwhleANW/quvq2HdViq8\n"
|
||||
"Mje2HBalfhrRfpDTHK8JUBSFjTzuWG42GxJRtgVbb8x2ElujAKGDCaetMO5VSGu7\n"
|
||||
"Fs5hw6iAFCpdXY0yhl+XUi2R8kwM2EPQ4lKO3jqkq0ClNmqn9a5jQWcCVt9yMLNS\n"
|
||||
"fLbHeI8EpiCf34ngIcrLXNkCgYEAzlcEZuKkC46xB+dNew8pMTUwSKZVm53BfPKD\n"
|
||||
"44QRN6imFbBjU9mAaJnwQbfp6dWKs834cGPolyM4++MeVfB42iZ88ksesgmZdUMD\n"
|
||||
"szkl6O0pOJs0I+HQZVdjRbadDZvD22MHQ3+oST1dJ3FVXz3Cdo9qPuT8esMO6f4r\n"
|
||||
"qfDH2s8CgYAXC/lWWHQ//PGP0pH4oiEXisx1K0X1u0xMGgrChxBRGRiKZUwNMIvJ\n"
|
||||
"TqUu7IKizK19cLHF/NBvxHYHFw+m7puNjn6T1RtRCUjRZT7Dx1VHfVosL9ih5DA8\n"
|
||||
"tpbZA5KGKcvHtB5DDgT0MHwzBZnb4Q//Rhovzn+HXZPsJTTgHHy3NQ==\n"
|
||||
"-----END RSA PRIVATE KEY-----\n"
|
||||
);
|
||||
const QString oldKeyString = QString("-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"MIIEpAIBAAKCAQEAsCHtJicDPWnvHSIKbnTZaJkIB9vgE0pmLdK580JUqBuonVbB\n"
|
||||
"y1QTy0ZQ7/TtqvLPgwPK88TR46OLO/QGCzo2+XxgJ85uy0xfuyUYRmSuw0drsErN\n"
|
||||
"mH8vU91lSBxsGDp9LtBbgHKoR23vMWZ34IxFRc55XphrIH48ijsMaL6bXBwF/3tD\n"
|
||||
"9T3lm2MpP1huyVNnIY9+GRRWCy4f9LMj/UGu/n4RtwwfpOZBBRwYkq5QkzA9lPm/\n"
|
||||
"VzF3MP1rKTMkvAw+Nfb383mkmc6MRnsa6uh6iDa9aVB7naegM13UJQX/PY1Ks6pO\n"
|
||||
"XDpy/MQ7iCh+HmYNq5dRmARyaNl9xIXJNhz1cQIDAQABAoIBAQCnEUc1LUQxeM5K\n"
|
||||
"wANNCqE+SgoIClPdeHC7fmrLh1ttqe6ib6ybBUFRS31yXs0hnfefunVEDKlaV8K2\n"
|
||||
"N52UAMAsngFHQNRvGh6kEWeZPd9Xc+N98TZbNCjcT+DGKc+Om8wqH5DrodZlCq4c\n"
|
||||
"GaoT4HnE4TjWtZTH2XXrWF9I66PKFWf070R44nvyVcvaZi4pC2YmURRPuGF6K1iK\n"
|
||||
"dH8zM6HHG1UGu2W6hLNn+K01IulG0Lb8eWNaNYMmtQWaxyp7I2IWkkecUs3nCuiR\n"
|
||||
"byFOoomCjdh8r9yZFvwxjGUhgtkALN9GCU0Mwve+s11IB2gevruN+q9/Qejbyfdm\n"
|
||||
"IlgLAeTRAoGBANRcVzW9CYeobCf+U9hKJFEOur8XO+J2mTMaELA0EjWpTJFAeIT7\n"
|
||||
"KeRpCRG4/vOSklxxRF6vP1EACA4Z+5BlN+FTipHHs+bSEgqkPZiiANDH7Zot5Iqv\n"
|
||||
"1q0fRyldNRZNZK7DWp08BPNVWGA/EnEuKJiURxnxBaxNXbUyMCdjxvMvAoGBANRT\n"
|
||||
"utbrqS/bAa/DcHKn3V6DRqBl3TDOfvCNjiKC84a67F2uXgzLIdMktr4d1NyCZVJd\n"
|
||||
"7/zVgWORLIdg1eAi6rYGoOvNV39wwga7CF+m9sBY0wAaKYCELe6L26r4aQHVCX6n\n"
|
||||
"rnIgUv+4o4itmU2iP0r3wlmDC9pDRQP82vfvQPlfAoGASwhleANW/quvq2HdViq8\n"
|
||||
"Mje2HBalfhrRfpDTHK8JUBSFjTzuWG42GxJRtgVbb8x2ElujAKGDCaetMO5VSGu7\n"
|
||||
"Fs5hw6iAFCpdXY0yhl+XUi2R8kwM2EPQ4lKO3jqkq0ClNmqn9a5jQWcCVt9yMLNS\n"
|
||||
"fLbHeI8EpiCf34ngIcrLXNkCgYEAzlcEZuKkC46xB+dNew8pMTUwSKZVm53BfPKD\n"
|
||||
"44QRN6imFbBjU9mAaJnwQbfp6dWKs834cGPolyM4++MeVfB42iZ88ksesgmZdUMD\n"
|
||||
"szkl6O0pOJs0I+HQZVdjRbadDZvD22MHQ3+oST1dJ3FVXz3Cdo9qPuT8esMO6f4r\n"
|
||||
"qfDH2s8CgYAXC/lWWHQ//PGP0pH4oiEXisx1K0X1u0xMGgrChxBRGRiKZUwNMIvJ\n"
|
||||
"TqUu7IKizK19cLHF/NBvxHYHFw+m7puNjn6T1RtRCUjRZT7Dx1VHfVosL9ih5DA8\n"
|
||||
"tpbZA5KGKcvHtB5DDgT0MHwzBZnb4Q//Rhovzn+HXZPsJTTgHHy3NQ==\n"
|
||||
"-----END RSA PRIVATE KEY-----\n");
|
||||
|
||||
const QString newKeyString = QString(
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n"
|
||||
"NhAAAAAwEAAQAAAQEAsCHtJicDPWnvHSIKbnTZaJkIB9vgE0pmLdK580JUqBuonVbBy1QT\n"
|
||||
"y0ZQ7/TtqvLPgwPK88TR46OLO/QGCzo2+XxgJ85uy0xfuyUYRmSuw0drsErNmH8vU91lSB\n"
|
||||
"xsGDp9LtBbgHKoR23vMWZ34IxFRc55XphrIH48ijsMaL6bXBwF/3tD9T3lm2MpP1huyVNn\n"
|
||||
"IY9+GRRWCy4f9LMj/UGu/n4RtwwfpOZBBRwYkq5QkzA9lPm/VzF3MP1rKTMkvAw+Nfb383\n"
|
||||
"mkmc6MRnsa6uh6iDa9aVB7naegM13UJQX/PY1Ks6pOXDpy/MQ7iCh+HmYNq5dRmARyaNl9\n"
|
||||
"xIXJNhz1cQAAA8DLsKINy7CiDQAAAAdzc2gtcnNhAAABAQCwIe0mJwM9ae8dIgpudNlomQ\n"
|
||||
"gH2+ATSmYt0rnzQlSoG6idVsHLVBPLRlDv9O2q8s+DA8rzxNHjo4s79AYLOjb5fGAnzm7L\n"
|
||||
"TF+7JRhGZK7DR2uwSs2Yfy9T3WVIHGwYOn0u0FuAcqhHbe8xZnfgjEVFznlemGsgfjyKOw\n"
|
||||
"xovptcHAX/e0P1PeWbYyk/WG7JU2chj34ZFFYLLh/0syP9Qa7+fhG3DB+k5kEFHBiSrlCT\n"
|
||||
"MD2U+b9XMXcw/WspMyS8DD419vfzeaSZzoxGexrq6HqINr1pUHudp6AzXdQlBf89jUqzqk\n"
|
||||
"5cOnL8xDuIKH4eZg2rl1GYBHJo2X3Ehck2HPVxAAAAAwEAAQAAAQEApxFHNS1EMXjOSsAD\n"
|
||||
"TQqhPkoKCApT3Xhwu35qy4dbbanuom+smwVBUUt9cl7NIZ33n7p1RAypWlfCtjedlADALJ\n"
|
||||
"4BR0DUbxoepBFnmT3fV3PjffE2WzQo3E/gxinPjpvMKh+Q66HWZQquHBmqE+B5xOE41rWU\n"
|
||||
"x9l161hfSOujyhVn9O9EeOJ78lXL2mYuKQtmJlEUT7hheitYinR/MzOhxxtVBrtluoSzZ/\n"
|
||||
"itNSLpRtC2/HljWjWDJrUFmscqeyNiFpJHnFLN5wrokW8hTqKJgo3YfK/cmRb8MYxlIYLZ\n"
|
||||
"ACzfRglNDML3vrNdSAdoHr67jfqvf0Ho28n3ZiJYCwHk0QAAAIAXC/lWWHQ//PGP0pH4oi\n"
|
||||
"EXisx1K0X1u0xMGgrChxBRGRiKZUwNMIvJTqUu7IKizK19cLHF/NBvxHYHFw+m7puNjn6T\n"
|
||||
"1RtRCUjRZT7Dx1VHfVosL9ih5DA8tpbZA5KGKcvHtB5DDgT0MHwzBZnb4Q//Rhovzn+HXZ\n"
|
||||
"PsJTTgHHy3NQAAAIEA1FxXNb0Jh6hsJ/5T2EokUQ66vxc74naZMxoQsDQSNalMkUB4hPsp\n"
|
||||
"5GkJEbj+85KSXHFEXq8/UQAIDhn7kGU34VOKkcez5tISCqQ9mKIA0Mftmi3kiq/WrR9HKV\n"
|
||||
"01Fk1krsNanTwE81VYYD8ScS4omJRHGfEFrE1dtTIwJ2PG8y8AAACBANRTutbrqS/bAa/D\n"
|
||||
"cHKn3V6DRqBl3TDOfvCNjiKC84a67F2uXgzLIdMktr4d1NyCZVJd7/zVgWORLIdg1eAi6r\n"
|
||||
"YGoOvNV39wwga7CF+m9sBY0wAaKYCELe6L26r4aQHVCX6nrnIgUv+4o4itmU2iP0r3wlmD\n"
|
||||
"C9pDRQP82vfvQPlfAAAABmlkX3JzYQECAwQ=\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n"
|
||||
);
|
||||
const QString newKeyString = QString("-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n"
|
||||
"NhAAAAAwEAAQAAAQEAsCHtJicDPWnvHSIKbnTZaJkIB9vgE0pmLdK580JUqBuonVbBy1QT\n"
|
||||
"y0ZQ7/TtqvLPgwPK88TR46OLO/QGCzo2+XxgJ85uy0xfuyUYRmSuw0drsErNmH8vU91lSB\n"
|
||||
"xsGDp9LtBbgHKoR23vMWZ34IxFRc55XphrIH48ijsMaL6bXBwF/3tD9T3lm2MpP1huyVNn\n"
|
||||
"IY9+GRRWCy4f9LMj/UGu/n4RtwwfpOZBBRwYkq5QkzA9lPm/VzF3MP1rKTMkvAw+Nfb383\n"
|
||||
"mkmc6MRnsa6uh6iDa9aVB7naegM13UJQX/PY1Ks6pOXDpy/MQ7iCh+HmYNq5dRmARyaNl9\n"
|
||||
"xIXJNhz1cQAAA8DLsKINy7CiDQAAAAdzc2gtcnNhAAABAQCwIe0mJwM9ae8dIgpudNlomQ\n"
|
||||
"gH2+ATSmYt0rnzQlSoG6idVsHLVBPLRlDv9O2q8s+DA8rzxNHjo4s79AYLOjb5fGAnzm7L\n"
|
||||
"TF+7JRhGZK7DR2uwSs2Yfy9T3WVIHGwYOn0u0FuAcqhHbe8xZnfgjEVFznlemGsgfjyKOw\n"
|
||||
"xovptcHAX/e0P1PeWbYyk/WG7JU2chj34ZFFYLLh/0syP9Qa7+fhG3DB+k5kEFHBiSrlCT\n"
|
||||
"MD2U+b9XMXcw/WspMyS8DD419vfzeaSZzoxGexrq6HqINr1pUHudp6AzXdQlBf89jUqzqk\n"
|
||||
"5cOnL8xDuIKH4eZg2rl1GYBHJo2X3Ehck2HPVxAAAAAwEAAQAAAQEApxFHNS1EMXjOSsAD\n"
|
||||
"TQqhPkoKCApT3Xhwu35qy4dbbanuom+smwVBUUt9cl7NIZ33n7p1RAypWlfCtjedlADALJ\n"
|
||||
"4BR0DUbxoepBFnmT3fV3PjffE2WzQo3E/gxinPjpvMKh+Q66HWZQquHBmqE+B5xOE41rWU\n"
|
||||
"x9l161hfSOujyhVn9O9EeOJ78lXL2mYuKQtmJlEUT7hheitYinR/MzOhxxtVBrtluoSzZ/\n"
|
||||
"itNSLpRtC2/HljWjWDJrUFmscqeyNiFpJHnFLN5wrokW8hTqKJgo3YfK/cmRb8MYxlIYLZ\n"
|
||||
"ACzfRglNDML3vrNdSAdoHr67jfqvf0Ho28n3ZiJYCwHk0QAAAIAXC/lWWHQ//PGP0pH4oi\n"
|
||||
"EXisx1K0X1u0xMGgrChxBRGRiKZUwNMIvJTqUu7IKizK19cLHF/NBvxHYHFw+m7puNjn6T\n"
|
||||
"1RtRCUjRZT7Dx1VHfVosL9ih5DA8tpbZA5KGKcvHtB5DDgT0MHwzBZnb4Q//Rhovzn+HXZ\n"
|
||||
"PsJTTgHHy3NQAAAIEA1FxXNb0Jh6hsJ/5T2EokUQ66vxc74naZMxoQsDQSNalMkUB4hPsp\n"
|
||||
"5GkJEbj+85KSXHFEXq8/UQAIDhn7kGU34VOKkcez5tISCqQ9mKIA0Mftmi3kiq/WrR9HKV\n"
|
||||
"01Fk1krsNanTwE81VYYD8ScS4omJRHGfEFrE1dtTIwJ2PG8y8AAACBANRTutbrqS/bAa/D\n"
|
||||
"cHKn3V6DRqBl3TDOfvCNjiKC84a67F2uXgzLIdMktr4d1NyCZVJd7/zVgWORLIdg1eAi6r\n"
|
||||
"YGoOvNV39wwga7CF+m9sBY0wAaKYCELe6L26r4aQHVCX6nrnIgUv+4o4itmU2iP0r3wlmD\n"
|
||||
"C9pDRQP82vfvQPlfAAAABmlkX3JzYQECAwQ=\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n");
|
||||
|
||||
const QByteArray oldKeyData = oldKeyString.toLatin1();
|
||||
const QByteArray newKeyData = newKeyString.toLatin1();
|
||||
@@ -295,38 +289,36 @@ void TestOpenSSHKey::testDecryptOpenSSHAES256CBC()
|
||||
|
||||
void TestOpenSSHKey::testDecryptRSAAES256CBC()
|
||||
{
|
||||
const QString keyString = QString(
|
||||
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"Proc-Type: 4,ENCRYPTED\n"
|
||||
"DEK-Info: AES-256-CBC,D51E3F558B621BD9384627762CBD16AC\n"
|
||||
"\n"
|
||||
"b6nr/06Gj8/Nw3ZFMePFyZeuBodExvZZtZPSH3t/2ArcxXOkoqUhLmlcY/JrvnBF\n"
|
||||
"JHc34wx/6Yng7mqtUMuk2iMemTzOj3JRx8zHUhwPLnjM/tmeOm0wBUb3WB4+rFZW\n"
|
||||
"s1PaIgeKywKgFK0UkcSRpMuSaxheWmHrtJkBsHTF7Tg3ogPL8Dc+nhQlbe/ZGaQb\n"
|
||||
"vMdSYcBMaXngS5ZiOafXeY8+l+IMMOZwy5vPTFQGqKHIzOxFhShs1hSExnwOXy69\n"
|
||||
"wxrA/QftjNEy5ixIeGT7iQfRB04tEVg0DjYphTPmI2ophzFlwJVBjhj2cmmnsMZg\n"
|
||||
"a2TdT/78KZsw2cA5ieMcU6d7Yz5p5nu5dyTbZonn6qWficdZRJwZnVb5ikPnJYbZ\n"
|
||||
"1YJRHHND+RWtpanxz7WhStscTCLeI9w9j2gqBJSjKDPgJaoMiA+tyEoakNlPYg+9\n"
|
||||
"DadJkBGP0g5E9zw0n4niqQ7eCxk7qolmW6Wtn2zL4UyeJKGi9NWFSGW9x/PmAIse\n"
|
||||
"E2KVodiJMRNa8/qUZcW58ZG2uRnFTsW4BXdmzOy/Zp53TVGWStBVLDcldSD03ItD\n"
|
||||
"JIWQWDgWp5xyVqPl+8mkW7xDY0GRVSJCyRkctQeGTGysy0BcNjgQQtiA3lPC0rY5\n"
|
||||
"m2VxrCYU1KuyHsAjs/V8THcW4a1UdPcVBg1QbCh29bMoM6u4MuXVt7rkwxAV9HJa\n"
|
||||
"VbwPsKy7V6G60KaAFIiOs0wdOzBZBoPGd9vBQOEzATh2FYJruDo2OfzEnhv25RxE\n"
|
||||
"1q+C/Jds9cWqaNY8kNtUG799XIKkjrC6KvnoV6UA4BkGs2DAcO9rnwtl/hToEoBe\n"
|
||||
"ZVj72dlTuS6l9rHqKaz2GI0k0SEt/ZoakPHeDRgPNcDvEZWitV8MuD6Mwb47Y88u\n"
|
||||
"sjBmS5k4sJOtB4bLg/UShcqYfkv2OTsK90qGQtba9vMk04Xh1FuxB4fHa5VoKrsX\n"
|
||||
"Th/LB34xoYugd16NPmLuawhSo70o4bT70GYpxnb4brGfjWiuthRdegAG9ESSX+M6\n"
|
||||
"rNKQPnn2GSroIpkoA4k0PaflcE5tpzeIiJdv0h65N3vw6MFnCaWy8sRSy9fMyRim\n"
|
||||
"U8QZB2jcp+YjUU/eny3scuh0Vqt6g1tfFbI84pCC5bArBirf63MeMtwDU/IVImax\n"
|
||||
"xzKOzl7k8ropA+rhAJ4Z9X35EmUncBXhf8g39w6nFuSlqjE6rMxCrsrehljQ1Iuz\n"
|
||||
"bujaJ2PKpf98OejHDKnMDOfBBq0DdeERCYWlCcqWSgrEgHh4vB5dEQAPP5bAkdZj\n"
|
||||
"m0Dq+gF99yadioxf3/MUZVTa1dHklBJJkXTYVPeyH07Th5j7bGCcVb9Zd2Ao/Dia\n"
|
||||
"MPWf6xViCC6d0njCLQY2R8mOR5OMVsdlFrsKZMQ/lqjS/WSM6URDkuGb0Cq94TQd\n"
|
||||
"7DoblcA50FTwYrVXMygWygbjzJxhcoJDHztzwoqLT/ghh+6zRg6R/fY222tHHbhz\n"
|
||||
"nePf421NILzfxnuW+GOwRCM5+IHE3OBS/PYDGijjRFHU4ky0rRRDE64m9CeFzeBh\n"
|
||||
"CnFvW6Yx3Hrh5tXBP7kRZ6KjyrPP7tI4ciVSJceSBLRzFmoBr10kRMm+VsUh2xZH\n"
|
||||
"-----END RSA PRIVATE KEY-----\n"
|
||||
);
|
||||
const QString keyString = QString("-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"Proc-Type: 4,ENCRYPTED\n"
|
||||
"DEK-Info: AES-256-CBC,D51E3F558B621BD9384627762CBD16AC\n"
|
||||
"\n"
|
||||
"b6nr/06Gj8/Nw3ZFMePFyZeuBodExvZZtZPSH3t/2ArcxXOkoqUhLmlcY/JrvnBF\n"
|
||||
"JHc34wx/6Yng7mqtUMuk2iMemTzOj3JRx8zHUhwPLnjM/tmeOm0wBUb3WB4+rFZW\n"
|
||||
"s1PaIgeKywKgFK0UkcSRpMuSaxheWmHrtJkBsHTF7Tg3ogPL8Dc+nhQlbe/ZGaQb\n"
|
||||
"vMdSYcBMaXngS5ZiOafXeY8+l+IMMOZwy5vPTFQGqKHIzOxFhShs1hSExnwOXy69\n"
|
||||
"wxrA/QftjNEy5ixIeGT7iQfRB04tEVg0DjYphTPmI2ophzFlwJVBjhj2cmmnsMZg\n"
|
||||
"a2TdT/78KZsw2cA5ieMcU6d7Yz5p5nu5dyTbZonn6qWficdZRJwZnVb5ikPnJYbZ\n"
|
||||
"1YJRHHND+RWtpanxz7WhStscTCLeI9w9j2gqBJSjKDPgJaoMiA+tyEoakNlPYg+9\n"
|
||||
"DadJkBGP0g5E9zw0n4niqQ7eCxk7qolmW6Wtn2zL4UyeJKGi9NWFSGW9x/PmAIse\n"
|
||||
"E2KVodiJMRNa8/qUZcW58ZG2uRnFTsW4BXdmzOy/Zp53TVGWStBVLDcldSD03ItD\n"
|
||||
"JIWQWDgWp5xyVqPl+8mkW7xDY0GRVSJCyRkctQeGTGysy0BcNjgQQtiA3lPC0rY5\n"
|
||||
"m2VxrCYU1KuyHsAjs/V8THcW4a1UdPcVBg1QbCh29bMoM6u4MuXVt7rkwxAV9HJa\n"
|
||||
"VbwPsKy7V6G60KaAFIiOs0wdOzBZBoPGd9vBQOEzATh2FYJruDo2OfzEnhv25RxE\n"
|
||||
"1q+C/Jds9cWqaNY8kNtUG799XIKkjrC6KvnoV6UA4BkGs2DAcO9rnwtl/hToEoBe\n"
|
||||
"ZVj72dlTuS6l9rHqKaz2GI0k0SEt/ZoakPHeDRgPNcDvEZWitV8MuD6Mwb47Y88u\n"
|
||||
"sjBmS5k4sJOtB4bLg/UShcqYfkv2OTsK90qGQtba9vMk04Xh1FuxB4fHa5VoKrsX\n"
|
||||
"Th/LB34xoYugd16NPmLuawhSo70o4bT70GYpxnb4brGfjWiuthRdegAG9ESSX+M6\n"
|
||||
"rNKQPnn2GSroIpkoA4k0PaflcE5tpzeIiJdv0h65N3vw6MFnCaWy8sRSy9fMyRim\n"
|
||||
"U8QZB2jcp+YjUU/eny3scuh0Vqt6g1tfFbI84pCC5bArBirf63MeMtwDU/IVImax\n"
|
||||
"xzKOzl7k8ropA+rhAJ4Z9X35EmUncBXhf8g39w6nFuSlqjE6rMxCrsrehljQ1Iuz\n"
|
||||
"bujaJ2PKpf98OejHDKnMDOfBBq0DdeERCYWlCcqWSgrEgHh4vB5dEQAPP5bAkdZj\n"
|
||||
"m0Dq+gF99yadioxf3/MUZVTa1dHklBJJkXTYVPeyH07Th5j7bGCcVb9Zd2Ao/Dia\n"
|
||||
"MPWf6xViCC6d0njCLQY2R8mOR5OMVsdlFrsKZMQ/lqjS/WSM6URDkuGb0Cq94TQd\n"
|
||||
"7DoblcA50FTwYrVXMygWygbjzJxhcoJDHztzwoqLT/ghh+6zRg6R/fY222tHHbhz\n"
|
||||
"nePf421NILzfxnuW+GOwRCM5+IHE3OBS/PYDGijjRFHU4ky0rRRDE64m9CeFzeBh\n"
|
||||
"CnFvW6Yx3Hrh5tXBP7kRZ6KjyrPP7tI4ciVSJceSBLRzFmoBr10kRMm+VsUh2xZH\n"
|
||||
"-----END RSA PRIVATE KEY-----\n");
|
||||
|
||||
const QByteArray keyData = keyString.toLatin1();
|
||||
|
||||
@@ -375,38 +367,36 @@ void TestOpenSSHKey::testDecryptOpenSSHAES256CTR()
|
||||
|
||||
void TestOpenSSHKey::testDecryptRSAAES256CTR()
|
||||
{
|
||||
const QString keyString = QString(
|
||||
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"Proc-Type: 4,ENCRYPTED\n"
|
||||
"DEK-Info: AES-256-CTR,192421854316290DFA8F469A1E8CB9BB\n"
|
||||
"\n"
|
||||
"3h7gUWua+jcvhYj1vUusbMdOG9j8SmNWFV5Hfersi8nF4ddsWEQDnMrRuhtIn4tU\n"
|
||||
"GcLY+SXguim5XXwF8gG1tmvpvFMhudTfX+0cIAX7eAVmqLy2RTA18DWqDwWokVP0\n"
|
||||
"RJPgRJJSorjMtu2F0YGVVjElW7pHIal7luNk3BDgYUMlgSg0BGOWb+9BkXcEnfc8\n"
|
||||
"KEwsJw2onoR2eXo6rYnczGaqPhAPu+I+PfUn0J8PFiffWc1KebRntLdRWeNsBS4p\n"
|
||||
"oxtqByzMYIu/WPSJJ5iFoNdKaWQPiZJB+juwI1wNLEtpzKkhpc7/6mOy87h+0eGV\n"
|
||||
"fF7javrbHv37eE+k2iZXrcLfvRpiBqt5+uhhCaM8TivBeUho5J38ru/wt/dk+OvY\n"
|
||||
"tzXboWA4zVnaYmqta1CkXYKOmb5a8TWEwtxmAuE6kCz/n3pPa6gwkwsyGI65IEyX\n"
|
||||
"ycJsbwUilAzXTcz5bIruGx38Sa9fndAN9llOQMS/hdyNs5W5dO1XZ5gU+ARPce+j\n"
|
||||
"+A2R8oCUv+2ciEu8z3F++U9aTRmTlD3xeIM0IWUFXKt8Y9fSRC5XoPCbZYNxnV6/\n"
|
||||
"hn9NPKCb890Faxies3MABOB5IZ0aTPWkx9ntxFhMaXyfkX2YthNO0GzAENPP9Knt\n"
|
||||
"DYhQePlKQ7sNi8+wzsHNeDxNuL/+Rib2MN3ankDtHIsqFz/Em+rD0+3ya8bLy3pP\n"
|
||||
"eeUiNpezL+uxI5llq/pikzK4sOgvH1r5YEkMxt9I09grkBwxR7DMBo0vgRE2MLiL\n"
|
||||
"nlri8TDwArC1+0gE8NspkkClsBOHXuVlGZo5lup2tn5MzERQcLvuFnAby/GnaVXQ\n"
|
||||
"Hm76teb1wMdL58FrdZsKR6e80E+F6JpTsz0a3XJqptgAwGsoxqizkUNJG5hRP8bi\n"
|
||||
"NBCFQZPeYi/GxgN5O2UkxhgRkKAcrHg+G87nhLk1ipsc214rb6iOspNizP6fGDuv\n"
|
||||
"/bsNTpYRgMNxCLh5Nv0HSUqckoNKOcIVe/9nF5/LLFGfhz95agjKTbBygThFK28N\n"
|
||||
"bnHq5fO9yKCMrGCRBQ6No1wwexyS4IAq17LcQP3k4w4n+Wt2GjO5HIldGOEyGqCE\n"
|
||||
"zeHYrPpGXF/yf3XTm00XghdQtVtRJptdddXVGZN3EN2w7/ghOSIIlsJO9C4IRgU3\n"
|
||||
"WkhX7oOpSE4wmXd5Ada+D1U46snW5nWANWko2NmQNVDeJcvuymL6t2ccNYeFWiA+\n"
|
||||
"Hlv0avBnqng7ZWPxYacqZI3+vU0rN9usN1pzwY/4NsBa34o3M7u6KvzEkyewbyUT\n"
|
||||
"VfXLJ8XRzb2u4NqQv0WiTBIRxvVB1sRPcrwB4HWKHwRFT8T7f1fefteROrKV7aKm\n"
|
||||
"Q48pckidDM0ORh1yIET8u24Mreo5eeWXjVJ9MHoM0486VySYxMwk8yp4tnaHx5kd\n"
|
||||
"fGlBbbwFOifhzjAk0u3KJRAG85t2GZhfTMo1IHS2kdu4Xs1N00ZmK0hjeGG+DCwy\n"
|
||||
"06ZKHOF5BHWU3SpQEjCsPDwfIpOINWGAJJnp6NIVf7FkHwViV50GWWGSZal4NqZy\n"
|
||||
"kR19buHiOb7KnGoPCw8MUmIym8v30FePhM4YQ7ASmRtsXlAhQNRX\n"
|
||||
"-----END RSA PRIVATE KEY-----\n"
|
||||
);
|
||||
const QString keyString = QString("-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"Proc-Type: 4,ENCRYPTED\n"
|
||||
"DEK-Info: AES-256-CTR,192421854316290DFA8F469A1E8CB9BB\n"
|
||||
"\n"
|
||||
"3h7gUWua+jcvhYj1vUusbMdOG9j8SmNWFV5Hfersi8nF4ddsWEQDnMrRuhtIn4tU\n"
|
||||
"GcLY+SXguim5XXwF8gG1tmvpvFMhudTfX+0cIAX7eAVmqLy2RTA18DWqDwWokVP0\n"
|
||||
"RJPgRJJSorjMtu2F0YGVVjElW7pHIal7luNk3BDgYUMlgSg0BGOWb+9BkXcEnfc8\n"
|
||||
"KEwsJw2onoR2eXo6rYnczGaqPhAPu+I+PfUn0J8PFiffWc1KebRntLdRWeNsBS4p\n"
|
||||
"oxtqByzMYIu/WPSJJ5iFoNdKaWQPiZJB+juwI1wNLEtpzKkhpc7/6mOy87h+0eGV\n"
|
||||
"fF7javrbHv37eE+k2iZXrcLfvRpiBqt5+uhhCaM8TivBeUho5J38ru/wt/dk+OvY\n"
|
||||
"tzXboWA4zVnaYmqta1CkXYKOmb5a8TWEwtxmAuE6kCz/n3pPa6gwkwsyGI65IEyX\n"
|
||||
"ycJsbwUilAzXTcz5bIruGx38Sa9fndAN9llOQMS/hdyNs5W5dO1XZ5gU+ARPce+j\n"
|
||||
"+A2R8oCUv+2ciEu8z3F++U9aTRmTlD3xeIM0IWUFXKt8Y9fSRC5XoPCbZYNxnV6/\n"
|
||||
"hn9NPKCb890Faxies3MABOB5IZ0aTPWkx9ntxFhMaXyfkX2YthNO0GzAENPP9Knt\n"
|
||||
"DYhQePlKQ7sNi8+wzsHNeDxNuL/+Rib2MN3ankDtHIsqFz/Em+rD0+3ya8bLy3pP\n"
|
||||
"eeUiNpezL+uxI5llq/pikzK4sOgvH1r5YEkMxt9I09grkBwxR7DMBo0vgRE2MLiL\n"
|
||||
"nlri8TDwArC1+0gE8NspkkClsBOHXuVlGZo5lup2tn5MzERQcLvuFnAby/GnaVXQ\n"
|
||||
"Hm76teb1wMdL58FrdZsKR6e80E+F6JpTsz0a3XJqptgAwGsoxqizkUNJG5hRP8bi\n"
|
||||
"NBCFQZPeYi/GxgN5O2UkxhgRkKAcrHg+G87nhLk1ipsc214rb6iOspNizP6fGDuv\n"
|
||||
"/bsNTpYRgMNxCLh5Nv0HSUqckoNKOcIVe/9nF5/LLFGfhz95agjKTbBygThFK28N\n"
|
||||
"bnHq5fO9yKCMrGCRBQ6No1wwexyS4IAq17LcQP3k4w4n+Wt2GjO5HIldGOEyGqCE\n"
|
||||
"zeHYrPpGXF/yf3XTm00XghdQtVtRJptdddXVGZN3EN2w7/ghOSIIlsJO9C4IRgU3\n"
|
||||
"WkhX7oOpSE4wmXd5Ada+D1U46snW5nWANWko2NmQNVDeJcvuymL6t2ccNYeFWiA+\n"
|
||||
"Hlv0avBnqng7ZWPxYacqZI3+vU0rN9usN1pzwY/4NsBa34o3M7u6KvzEkyewbyUT\n"
|
||||
"VfXLJ8XRzb2u4NqQv0WiTBIRxvVB1sRPcrwB4HWKHwRFT8T7f1fefteROrKV7aKm\n"
|
||||
"Q48pckidDM0ORh1yIET8u24Mreo5eeWXjVJ9MHoM0486VySYxMwk8yp4tnaHx5kd\n"
|
||||
"fGlBbbwFOifhzjAk0u3KJRAG85t2GZhfTMo1IHS2kdu4Xs1N00ZmK0hjeGG+DCwy\n"
|
||||
"06ZKHOF5BHWU3SpQEjCsPDwfIpOINWGAJJnp6NIVf7FkHwViV50GWWGSZal4NqZy\n"
|
||||
"kR19buHiOb7KnGoPCw8MUmIym8v30FePhM4YQ7ASmRtsXlAhQNRX\n"
|
||||
"-----END RSA PRIVATE KEY-----\n");
|
||||
|
||||
const QByteArray keyData = keyString.toLatin1();
|
||||
|
||||
@@ -423,16 +413,14 @@ void TestOpenSSHKey::testDecryptRSAAES256CTR()
|
||||
|
||||
void TestOpenSSHKey::testDecryptUTF8()
|
||||
{
|
||||
const QString keyString = QString(
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDtSl4OvT\n"
|
||||
"H/wHay2dvjOnpIAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIIhrBrn6rb+d3GwF\n"
|
||||
"ifpJ6gYut95lXvwypiQmu9ZpA8H9AAAAsD85Gpn2mbVEWq3ygx11wBnN5mUQXnMuP48rLv\n"
|
||||
"0qwm12IihOkrR925ledwN2Sa5mkkL0XjDz6SsKfIFhFa84hUHQdw5zPR8yVGRWLzkNDmo7\n"
|
||||
"WXNpnoE4ebsX2j0TsBNjP80RUcJdjSXidkt3+aZjaCfquO8cBQn4GJJSDSPwFJYlJeSD/h\n"
|
||||
"vpb72MEQchOD3NNMORYTJ5sOJ73RayhhmwjTVlrG+zYAw6fXW0YXX3+5LE\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n"
|
||||
);
|
||||
const QString keyString = QString("-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDtSl4OvT\n"
|
||||
"H/wHay2dvjOnpIAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIIhrBrn6rb+d3GwF\n"
|
||||
"ifpJ6gYut95lXvwypiQmu9ZpA8H9AAAAsD85Gpn2mbVEWq3ygx11wBnN5mUQXnMuP48rLv\n"
|
||||
"0qwm12IihOkrR925ledwN2Sa5mkkL0XjDz6SsKfIFhFa84hUHQdw5zPR8yVGRWLzkNDmo7\n"
|
||||
"WXNpnoE4ebsX2j0TsBNjP80RUcJdjSXidkt3+aZjaCfquO8cBQn4GJJSDSPwFJYlJeSD/h\n"
|
||||
"vpb72MEQchOD3NNMORYTJ5sOJ73RayhhmwjTVlrG+zYAw6fXW0YXX3+5LE\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n");
|
||||
|
||||
const QByteArray keyData = keyString.toLatin1();
|
||||
|
||||
|
||||
130
tests/TestPasswordGenerator.cpp
Normal file
130
tests/TestPasswordGenerator.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program 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 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TestPasswordGenerator.h"
|
||||
#include "core/PasswordGenerator.h"
|
||||
#include "crypto/Crypto.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QTest>
|
||||
|
||||
QTEST_GUILESS_MAIN(TestPasswordGenerator)
|
||||
|
||||
void TestPasswordGenerator::initTestCase()
|
||||
{
|
||||
QVERIFY(Crypto::init());
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testCharClasses()
|
||||
{
|
||||
PasswordGenerator generator;
|
||||
QVERIFY(!generator.isValid());
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters);
|
||||
generator.setLength(16);
|
||||
QVERIFY(generator.isValid());
|
||||
QCOMPARE(generator.generatePassword().size(), 16);
|
||||
|
||||
generator.setLength(2000);
|
||||
QString password = generator.generatePassword();
|
||||
QCOMPARE(password.size(), 2000);
|
||||
QRegularExpression regex(R"(^[a-z]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::UpperLetters);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[A-Z]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Numbers);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^\d+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Braces);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[\(\)\[\]\{\}]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Punctuation);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[\.,:;]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Quotes);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^["']+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Dashes);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[\-/\\_|]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Math);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[!\*\+\-<=>\?]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Logograms);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[#`~%&^$@]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::EASCII);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[^a-zA-Z0-9\.,:;"'\-/\\_|!\*\+\-<=>\?#`~%&^$@]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Braces);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^[a-zA-Z\(\)\[\]\{\}]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::Quotes | PasswordGenerator::CharClass::Numbers
|
||||
| PasswordGenerator::CharClass::Dashes);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern(R"(^["'\d\-/\\_|]+$)");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
}
|
||||
|
||||
void TestPasswordGenerator::testLookalikeExclusion()
|
||||
{
|
||||
PasswordGenerator generator;
|
||||
generator.setLength(2000);
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters);
|
||||
QVERIFY(generator.isValid());
|
||||
QString password = generator.generatePassword();
|
||||
QCOMPARE(password.size(), 2000);
|
||||
|
||||
generator.setFlags(PasswordGenerator::GeneratorFlag::ExcludeLookAlike);
|
||||
password = generator.generatePassword();
|
||||
QRegularExpression regex("^[^lI0]+$");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Numbers);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern("^[^lI01]+$");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
|
||||
generator.setCharClasses(PasswordGenerator::CharClass::LowerLetters | PasswordGenerator::CharClass::UpperLetters
|
||||
| PasswordGenerator::CharClass::Numbers | PasswordGenerator::CharClass::EASCII);
|
||||
password = generator.generatePassword();
|
||||
regex.setPattern("^[^lI01﹒]+$");
|
||||
QVERIFY(regex.match(password).hasMatch());
|
||||
}
|
||||
33
tests/TestPasswordGenerator.h
Normal file
33
tests/TestPasswordGenerator.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program 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 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef KEEPASSXC_TESTPASSWORDGENERATOR_H
|
||||
#define KEEPASSXC_TESTPASSWORDGENERATOR_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class TestPasswordGenerator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void testCharClasses();
|
||||
void testLookalikeExclusion();
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_TESTPASSWORDGENERATOR_H
|
||||
@@ -26,76 +26,171 @@
|
||||
#include "streams/SymmetricCipherStream.h"
|
||||
|
||||
QTEST_GUILESS_MAIN(TestSymmetricCipher)
|
||||
Q_DECLARE_METATYPE(SymmetricCipher::Algorithm);
|
||||
Q_DECLARE_METATYPE(SymmetricCipher::Mode);
|
||||
Q_DECLARE_METATYPE(SymmetricCipher::Direction);
|
||||
|
||||
void TestSymmetricCipher::initTestCase()
|
||||
{
|
||||
QVERIFY(Crypto::init());
|
||||
}
|
||||
|
||||
void TestSymmetricCipher::testAes128CbcEncryption()
|
||||
void TestSymmetricCipher::testAlgorithmToCipher()
|
||||
{
|
||||
QCOMPARE(SymmetricCipher::algorithmToCipher(SymmetricCipher::Algorithm::Aes128), KeePass2::CIPHER_AES128);
|
||||
QCOMPARE(SymmetricCipher::algorithmToCipher(SymmetricCipher::Algorithm::Aes256), KeePass2::CIPHER_AES256);
|
||||
QCOMPARE(SymmetricCipher::algorithmToCipher(SymmetricCipher::Algorithm::Twofish), KeePass2::CIPHER_TWOFISH);
|
||||
QCOMPARE(SymmetricCipher::algorithmToCipher(SymmetricCipher::Algorithm::ChaCha20), KeePass2::CIPHER_CHACHA20);
|
||||
QCOMPARE(SymmetricCipher::algorithmToCipher(SymmetricCipher::Algorithm::InvalidAlgorithm), QUuid());
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
void TestSymmetricCipher::testEncryptionDecryption_data()
|
||||
{
|
||||
QTest::addColumn<SymmetricCipher::Algorithm>("algorithm");
|
||||
QTest::addColumn<SymmetricCipher::Mode>("mode");
|
||||
QTest::addColumn<SymmetricCipher::Direction>("direction");
|
||||
QTest::addColumn<QByteArray>("key");
|
||||
QTest::addColumn<QByteArray>("iv");
|
||||
QTest::addColumn<QByteArray>("plainText");
|
||||
QTest::addColumn<QByteArray>("cipherText");
|
||||
|
||||
// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
QTest::newRow("AES128-CBC Encryption")
|
||||
<< SymmetricCipher::Aes128
|
||||
<< SymmetricCipher::Cbc
|
||||
<< SymmetricCipher::Encrypt
|
||||
<< QByteArray::fromHex("2b7e151628aed2a6abf7158809cf4f3c")
|
||||
<< QByteArray::fromHex("000102030405060708090a0b0c0d0e0f")
|
||||
<< QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
|
||||
<< QByteArray::fromHex("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2");
|
||||
|
||||
QTest::newRow("AES128-CBC Decryption")
|
||||
<< SymmetricCipher::Aes128
|
||||
<< SymmetricCipher::Cbc
|
||||
<< SymmetricCipher::Decrypt
|
||||
<< QByteArray::fromHex("2b7e151628aed2a6abf7158809cf4f3c")
|
||||
<< QByteArray::fromHex("000102030405060708090a0b0c0d0e0f")
|
||||
<< QByteArray::fromHex("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2")
|
||||
<< QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51");
|
||||
|
||||
QTest::newRow("AES256-CBC Encryption")
|
||||
<< SymmetricCipher::Aes256
|
||||
<< SymmetricCipher::Cbc
|
||||
<< SymmetricCipher::Encrypt
|
||||
<< QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4")
|
||||
<< QByteArray::fromHex("000102030405060708090a0b0c0d0e0f")
|
||||
<< QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
|
||||
<< QByteArray::fromHex("f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d");
|
||||
|
||||
QTest::newRow("AES256-CBC Decryption")
|
||||
<< SymmetricCipher::Aes256
|
||||
<< SymmetricCipher::Cbc
|
||||
<< SymmetricCipher::Decrypt
|
||||
<< QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4")
|
||||
<< QByteArray::fromHex("000102030405060708090a0b0c0d0e0f")
|
||||
<< QByteArray::fromHex("f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d")
|
||||
<< QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51");
|
||||
|
||||
QTest::newRow("AES256-CTR Encryption")
|
||||
<< SymmetricCipher::Aes256
|
||||
<< SymmetricCipher::Ctr
|
||||
<< SymmetricCipher::Encrypt
|
||||
<< QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4")
|
||||
<< QByteArray::fromHex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")
|
||||
<< QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
|
||||
<< QByteArray::fromHex("601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c5");
|
||||
|
||||
QTest::newRow("AES256-CTR Decryption")
|
||||
<< SymmetricCipher::Aes256
|
||||
<< SymmetricCipher::Ctr
|
||||
<< SymmetricCipher::Decrypt
|
||||
<< QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4")
|
||||
<< QByteArray::fromHex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")
|
||||
<< QByteArray::fromHex("601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c5")
|
||||
<< QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51");
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
void TestSymmetricCipher::testEncryptionDecryption()
|
||||
{
|
||||
QFETCH(SymmetricCipher::Algorithm, algorithm);
|
||||
QFETCH(SymmetricCipher::Mode, mode);
|
||||
QFETCH(SymmetricCipher::Direction, direction);
|
||||
QFETCH(QByteArray, key);
|
||||
QFETCH(QByteArray, iv);
|
||||
QFETCH(QByteArray, plainText);
|
||||
QFETCH(QByteArray, cipherText);
|
||||
|
||||
QByteArray key = QByteArray::fromHex("2b7e151628aed2a6abf7158809cf4f3c");
|
||||
QByteArray iv = QByteArray::fromHex("000102030405060708090a0b0c0d0e0f");
|
||||
QByteArray plainText = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a");
|
||||
plainText.append(QByteArray::fromHex("ae2d8a571e03ac9c9eb76fac45af8e51"));
|
||||
QByteArray cipherText = QByteArray::fromHex("7649abac8119b246cee98e9b12e9197d");
|
||||
cipherText.append(QByteArray::fromHex("5086cb9b507219ee95db113a917678b2"));
|
||||
bool ok;
|
||||
|
||||
SymmetricCipher cipher(SymmetricCipher::Aes128, SymmetricCipher::Cbc, SymmetricCipher::Encrypt);
|
||||
SymmetricCipher cipher(algorithm, mode, direction);
|
||||
QVERIFY(cipher.init(key, iv));
|
||||
QCOMPARE(cipher.blockSize(), 16);
|
||||
QCOMPARE(cipher.process(plainText, &ok), cipherText);
|
||||
QVERIFY(ok);
|
||||
|
||||
QBuffer buffer;
|
||||
SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes128, SymmetricCipher::Cbc, SymmetricCipher::Encrypt);
|
||||
QVERIFY(stream.init(key, iv));
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QVERIFY(stream.open(QIODevice::WriteOnly));
|
||||
QVERIFY(stream.reset());
|
||||
if (mode == SymmetricCipher::Cbc) {
|
||||
QBuffer buffer;
|
||||
SymmetricCipherStream stream(&buffer, algorithm, mode, direction);
|
||||
QVERIFY(stream.init(key, iv));
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QVERIFY(stream.open(QIODevice::WriteOnly));
|
||||
QVERIFY(stream.reset());
|
||||
|
||||
buffer.reset();
|
||||
buffer.buffer().clear();
|
||||
QCOMPARE(stream.write(plainText.left(16)), qint64(16));
|
||||
QCOMPARE(buffer.data(), cipherText.left(16));
|
||||
QVERIFY(stream.reset());
|
||||
// make sure padding is written
|
||||
QCOMPARE(buffer.data().size(), 32);
|
||||
buffer.reset();
|
||||
buffer.buffer().clear();
|
||||
QCOMPARE(stream.write(plainText.left(16)), qint64(16));
|
||||
QCOMPARE(buffer.data(), cipherText.left(16));
|
||||
QVERIFY(stream.reset());
|
||||
// make sure padding is written
|
||||
QCOMPARE(buffer.data().size(), 32);
|
||||
|
||||
buffer.reset();
|
||||
buffer.buffer().clear();
|
||||
QCOMPARE(stream.write(plainText.left(10)), qint64(10));
|
||||
QVERIFY(buffer.data().isEmpty());
|
||||
buffer.reset();
|
||||
buffer.buffer().clear();
|
||||
QCOMPARE(stream.write(plainText.left(10)), qint64(10));
|
||||
QVERIFY(buffer.data().isEmpty());
|
||||
|
||||
QVERIFY(stream.reset());
|
||||
buffer.reset();
|
||||
buffer.buffer().clear();
|
||||
QCOMPARE(stream.write(plainText.left(10)), qint64(10));
|
||||
stream.close();
|
||||
QCOMPARE(buffer.data().size(), 16);
|
||||
QVERIFY(stream.reset());
|
||||
buffer.reset();
|
||||
buffer.buffer().clear();
|
||||
QCOMPARE(stream.write(plainText.left(10)), qint64(10));
|
||||
stream.close();
|
||||
QCOMPARE(buffer.data().size(), 16);
|
||||
}
|
||||
}
|
||||
|
||||
void TestSymmetricCipher::testAes128CbcDecryption()
|
||||
void TestSymmetricCipher::testAesCbcPadding_data()
|
||||
{
|
||||
QByteArray key = QByteArray::fromHex("2b7e151628aed2a6abf7158809cf4f3c");
|
||||
QByteArray iv = QByteArray::fromHex("000102030405060708090a0b0c0d0e0f");
|
||||
QByteArray cipherText = QByteArray::fromHex("7649abac8119b246cee98e9b12e9197d");
|
||||
cipherText.append(QByteArray::fromHex("5086cb9b507219ee95db113a917678b2"));
|
||||
QByteArray plainText = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a");
|
||||
plainText.append(QByteArray::fromHex("ae2d8a571e03ac9c9eb76fac45af8e51"));
|
||||
bool ok;
|
||||
QTest::addColumn<QByteArray>("key");
|
||||
QTest::addColumn<QByteArray>("iv");
|
||||
QTest::addColumn<QByteArray>("cipherText");
|
||||
QTest::addColumn<QByteArray>("plainText");
|
||||
QTest::addColumn<QByteArray>("padding");
|
||||
|
||||
SymmetricCipher cipher(SymmetricCipher::Aes128, SymmetricCipher::Cbc, SymmetricCipher::Decrypt);
|
||||
QVERIFY(cipher.init(key, iv));
|
||||
QCOMPARE(cipher.blockSize(), 16);
|
||||
QCOMPARE(cipher.process(cipherText, &ok), plainText);
|
||||
QVERIFY(ok);
|
||||
QTest::newRow("AES128") << QByteArray::fromHex("2b7e151628aed2a6abf7158809cf4f3c")
|
||||
<< QByteArray::fromHex("000102030405060708090a0b0c0d0e0f")
|
||||
<< QByteArray::fromHex("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2")
|
||||
<< QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
|
||||
<< QByteArray::fromHex("55e21d7100b988ffec32feeafaf23538");
|
||||
|
||||
QTest::newRow("AES256") << QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4")
|
||||
<< QByteArray::fromHex("000102030405060708090a0b0c0d0e0f")
|
||||
<< QByteArray::fromHex("f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d")
|
||||
<< QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
|
||||
<< QByteArray::fromHex("3a3aa5e0213db1a9901f9036cf5102d2");
|
||||
}
|
||||
|
||||
void TestSymmetricCipher::testAesCbcPadding()
|
||||
{
|
||||
QFETCH(QByteArray, key);
|
||||
QFETCH(QByteArray, iv);
|
||||
QFETCH(QByteArray, cipherText);
|
||||
QFETCH(QByteArray, plainText);
|
||||
QFETCH(QByteArray, padding);
|
||||
|
||||
// padded with 16 0x10 bytes
|
||||
QByteArray cipherTextPadded = cipherText + QByteArray::fromHex("55e21d7100b988ffec32feeafaf23538");
|
||||
QByteArray cipherTextPadded = cipherText + padding;
|
||||
|
||||
QBuffer buffer(&cipherTextPadded);
|
||||
SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes128, SymmetricCipher::Cbc, SymmetricCipher::Decrypt);
|
||||
QVERIFY(stream.init(key, iv));
|
||||
@@ -114,126 +209,47 @@ void TestSymmetricCipher::testAes128CbcDecryption()
|
||||
QCOMPARE(stream.read(100), plainText);
|
||||
}
|
||||
|
||||
void TestSymmetricCipher::testAes256CbcEncryption()
|
||||
void TestSymmetricCipher::testInplaceEcb_data()
|
||||
{
|
||||
// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
QTest::addColumn<QByteArray>("key");
|
||||
QTest::addColumn<QByteArray>("plainText");
|
||||
QTest::addColumn<QByteArray>("cipherText");
|
||||
|
||||
QByteArray key = QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
|
||||
QByteArray iv = QByteArray::fromHex("000102030405060708090a0b0c0d0e0f");
|
||||
QByteArray plainText = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a");
|
||||
plainText.append(QByteArray::fromHex("ae2d8a571e03ac9c9eb76fac45af8e51"));
|
||||
QByteArray cipherText = QByteArray::fromHex("f58c4c04d6e5f1ba779eabfb5f7bfbd6");
|
||||
cipherText.append(QByteArray::fromHex("9cfc4e967edb808d679f777bc6702c7d"));
|
||||
bool ok;
|
||||
|
||||
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Encrypt);
|
||||
QVERIFY(cipher.init(key, iv));
|
||||
QCOMPARE(cipher.blockSize(), 16);
|
||||
|
||||
QCOMPARE(cipher.process(plainText, &ok), cipherText);
|
||||
QVERIFY(ok);
|
||||
|
||||
QBuffer buffer;
|
||||
SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Encrypt);
|
||||
QVERIFY(stream.init(key, iv));
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QVERIFY(stream.open(QIODevice::WriteOnly));
|
||||
QVERIFY(stream.reset());
|
||||
|
||||
buffer.reset();
|
||||
buffer.buffer().clear();
|
||||
QCOMPARE(stream.write(plainText.left(16)), qint64(16));
|
||||
QCOMPARE(buffer.data(), cipherText.left(16));
|
||||
QVERIFY(stream.reset());
|
||||
// make sure padding is written
|
||||
QCOMPARE(buffer.data().size(), 32);
|
||||
|
||||
buffer.reset();
|
||||
buffer.buffer().clear();
|
||||
QCOMPARE(stream.write(plainText.left(10)), qint64(10));
|
||||
QVERIFY(buffer.data().isEmpty());
|
||||
|
||||
QVERIFY(stream.reset());
|
||||
buffer.reset();
|
||||
buffer.buffer().clear();
|
||||
QCOMPARE(stream.write(plainText.left(10)), qint64(10));
|
||||
stream.close();
|
||||
QCOMPARE(buffer.data().size(), 16);
|
||||
QTest::newRow("AES128") << QByteArray::fromHex("2b7e151628aed2a6abf7158809cf4f3c")
|
||||
<< QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a")
|
||||
<< QByteArray::fromHex("3ad77bb40d7a3660a89ecaf32466ef97");
|
||||
}
|
||||
|
||||
void TestSymmetricCipher::testAes256CbcDecryption()
|
||||
void TestSymmetricCipher::testInplaceEcb()
|
||||
{
|
||||
QByteArray key = QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
|
||||
QByteArray iv = QByteArray::fromHex("000102030405060708090a0b0c0d0e0f");
|
||||
QByteArray cipherText = QByteArray::fromHex("f58c4c04d6e5f1ba779eabfb5f7bfbd6");
|
||||
cipherText.append(QByteArray::fromHex("9cfc4e967edb808d679f777bc6702c7d"));
|
||||
QByteArray plainText = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a");
|
||||
plainText.append(QByteArray::fromHex("ae2d8a571e03ac9c9eb76fac45af8e51"));
|
||||
bool ok;
|
||||
QFETCH(QByteArray, key);
|
||||
QFETCH(QByteArray, plainText);
|
||||
QFETCH(QByteArray, cipherText);
|
||||
|
||||
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt);
|
||||
QVERIFY(cipher.init(key, iv));
|
||||
QCOMPARE(cipher.blockSize(), 16);
|
||||
SymmetricCipher cipherInPlaceEnc(SymmetricCipher::Aes128, SymmetricCipher::Ecb, SymmetricCipher::Encrypt);
|
||||
QVERIFY(cipherInPlaceEnc.init(key, QByteArray(16, 0)));
|
||||
QCOMPARE(cipherInPlaceEnc.blockSize(), 16);
|
||||
auto data = QByteArray(plainText);
|
||||
QVERIFY(cipherInPlaceEnc.processInPlace(data));
|
||||
QCOMPARE(data, cipherText);
|
||||
|
||||
QCOMPARE(cipher.process(cipherText, &ok), plainText);
|
||||
QVERIFY(ok);
|
||||
SymmetricCipher cipherInPlaceDec(SymmetricCipher::Aes128, SymmetricCipher::Ecb, SymmetricCipher::Decrypt);
|
||||
QVERIFY(cipherInPlaceDec.init(key, QByteArray(16, 0)));
|
||||
QCOMPARE(cipherInPlaceDec.blockSize(), 16);
|
||||
QVERIFY(cipherInPlaceDec.processInPlace(data));
|
||||
QCOMPARE(data, plainText);
|
||||
|
||||
// padded with 16 0x16 bytes
|
||||
QByteArray cipherTextPadded = cipherText + QByteArray::fromHex("3a3aa5e0213db1a9901f9036cf5102d2");
|
||||
QBuffer buffer(&cipherTextPadded);
|
||||
SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt);
|
||||
QVERIFY(stream.init(key, iv));
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
QVERIFY(stream.open(QIODevice::ReadOnly));
|
||||
SymmetricCipher cipherInPlaceEnc2(SymmetricCipher::Aes128, SymmetricCipher::Ecb, SymmetricCipher::Encrypt);
|
||||
QVERIFY(cipherInPlaceEnc2.init(key, QByteArray(16, 0)));
|
||||
QCOMPARE(cipherInPlaceEnc2.blockSize(), 16);
|
||||
data = QByteArray(plainText);
|
||||
QVERIFY(cipherInPlaceEnc2.processInPlace(data, 100));
|
||||
|
||||
QCOMPARE(stream.read(10), plainText.left(10));
|
||||
buffer.reset();
|
||||
QVERIFY(stream.reset());
|
||||
QCOMPARE(stream.read(20), plainText.left(20));
|
||||
buffer.reset();
|
||||
QVERIFY(stream.reset());
|
||||
QCOMPARE(stream.read(16), plainText.left(16));
|
||||
buffer.reset();
|
||||
QVERIFY(stream.reset());
|
||||
QCOMPARE(stream.read(100), plainText);
|
||||
}
|
||||
|
||||
void TestSymmetricCipher::testAes256CtrEncryption()
|
||||
{
|
||||
// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
|
||||
QByteArray key = QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
|
||||
QByteArray ctr = QByteArray::fromHex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
|
||||
QByteArray plainText = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a");
|
||||
plainText.append(QByteArray::fromHex("ae2d8a571e03ac9c9eb76fac45af8e51"));
|
||||
QByteArray cipherText = QByteArray::fromHex("601ec313775789a5b7a7f504bbf3d228");
|
||||
cipherText.append(QByteArray::fromHex("f443e3ca4d62b59aca84e990cacaf5c5"));
|
||||
bool ok;
|
||||
|
||||
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ctr, SymmetricCipher::Encrypt);
|
||||
QVERIFY(cipher.init(key, ctr));
|
||||
QCOMPARE(cipher.blockSize(), 16);
|
||||
|
||||
QCOMPARE(cipher.process(plainText, &ok), cipherText);
|
||||
QVERIFY(ok);
|
||||
}
|
||||
|
||||
void TestSymmetricCipher::testAes256CtrDecryption()
|
||||
{
|
||||
QByteArray key = QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
|
||||
QByteArray ctr = QByteArray::fromHex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
|
||||
QByteArray cipherText = QByteArray::fromHex("601ec313775789a5b7a7f504bbf3d228");
|
||||
cipherText.append(QByteArray::fromHex("f443e3ca4d62b59aca84e990cacaf5c5"));
|
||||
QByteArray plainText = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a");
|
||||
plainText.append(QByteArray::fromHex("ae2d8a571e03ac9c9eb76fac45af8e51"));
|
||||
bool ok;
|
||||
|
||||
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ctr, SymmetricCipher::Decrypt);
|
||||
QVERIFY(cipher.init(key, ctr));
|
||||
QCOMPARE(cipher.blockSize(), 16);
|
||||
|
||||
QCOMPARE(cipher.process(cipherText, &ok), plainText);
|
||||
QVERIFY(ok);
|
||||
SymmetricCipher cipherInPlaceDec2(SymmetricCipher::Aes128, SymmetricCipher::Ecb, SymmetricCipher::Decrypt);
|
||||
QVERIFY(cipherInPlaceDec2.init(key, QByteArray(16, 0)));
|
||||
QCOMPARE(cipherInPlaceDec2.blockSize(), 16);
|
||||
QVERIFY(cipherInPlaceDec2.processInPlace(data, 100));
|
||||
QCOMPARE(data, plainText);
|
||||
}
|
||||
|
||||
void TestSymmetricCipher::testTwofish256CbcEncryption()
|
||||
|
||||
@@ -27,12 +27,13 @@ class TestSymmetricCipher : public QObject
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void testAes128CbcEncryption();
|
||||
void testAes128CbcDecryption();
|
||||
void testAes256CbcEncryption();
|
||||
void testAes256CbcDecryption();
|
||||
void testAes256CtrEncryption();
|
||||
void testAes256CtrDecryption();
|
||||
void testAlgorithmToCipher();
|
||||
void testEncryptionDecryption_data();
|
||||
void testEncryptionDecryption();
|
||||
void testAesCbcPadding_data();
|
||||
void testAesCbcPadding();
|
||||
void testInplaceEcb_data();
|
||||
void testInplaceEcb();
|
||||
void testTwofish256CbcEncryption();
|
||||
void testTwofish256CbcDecryption();
|
||||
void testSalsa20();
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace
|
||||
{
|
||||
return wholes + QLocale().decimalPoint() + fractions + " " + unit;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void TestTools::testHumanReadableFileSize()
|
||||
{
|
||||
|
||||
Binary file not shown.
BIN
tests/data/NewDatabase2.kdbx
Normal file
BIN
tests/data/NewDatabase2.kdbx
Normal file
Binary file not shown.
@@ -15,6 +15,6 @@
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
|
||||
add_unit_test(NAME testgui SOURCES TestGui.cpp TemporaryFile.cpp LIBS ${TEST_LIBRARIES})
|
||||
add_unit_test(NAME testgui SOURCES TestGui.cpp ../util/TemporaryFile.cpp LIBS ${TEST_LIBRARIES})
|
||||
|
||||
add_unit_test(NAME testguipixmaps SOURCES TestGuiPixmaps.cpp LIBS ${TEST_LIBRARIES})
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Danny Su <contact@dannysu.com>
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program 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 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TemporaryFile.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
const QString TemporaryFile::SUFFIX = ".win";
|
||||
|
||||
TemporaryFile::~TemporaryFile()
|
||||
{
|
||||
if (m_tempFile.autoRemove()) {
|
||||
m_file.remove();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool TemporaryFile::open()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
// Still call QTemporaryFile::open() so that it figures out the temporary
|
||||
// file name to use. Assuming that by appending the SUFFIX to whatever
|
||||
// QTemporaryFile chooses is also an available file.
|
||||
bool tempFileOpened = m_tempFile.open();
|
||||
if (tempFileOpened) {
|
||||
m_file.setFileName(filePath());
|
||||
return m_file.open(QIODevice::WriteOnly);
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return m_tempFile.open();
|
||||
#endif
|
||||
}
|
||||
|
||||
void TemporaryFile::close()
|
||||
{
|
||||
m_tempFile.close();
|
||||
#ifdef Q_OS_WIN
|
||||
m_file.close();
|
||||
#endif
|
||||
}
|
||||
|
||||
qint64 TemporaryFile::write(const char* data, qint64 maxSize)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return m_file.write(data, maxSize);
|
||||
#else
|
||||
return m_tempFile.write(data, maxSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
qint64 TemporaryFile::write(const QByteArray& byteArray)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return m_file.write(byteArray);
|
||||
#else
|
||||
return m_tempFile.write(byteArray);
|
||||
#endif
|
||||
}
|
||||
|
||||
QString TemporaryFile::fileName() const
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return QFileInfo(m_tempFile).fileName() + TemporaryFile::SUFFIX;
|
||||
#else
|
||||
return QFileInfo(m_tempFile).fileName();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString TemporaryFile::filePath() const
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return m_tempFile.fileName() + TemporaryFile::SUFFIX;
|
||||
#else
|
||||
return m_tempFile.fileName();
|
||||
#endif
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Danny Su <contact@dannysu.com>
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program 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 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef KEEPASSX_TEMPORARYFILE_H
|
||||
#define KEEPASSX_TEMPORARYFILE_H
|
||||
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
/**
|
||||
* QTemporaryFile::close() doesn't actually close the file according to
|
||||
* http://doc.qt.io/qt-5/qtemporaryfile.html: "For as long as the
|
||||
* QTemporaryFile object itself is not destroyed, the unique temporary file
|
||||
* will exist and be kept open internally by QTemporaryFile."
|
||||
*
|
||||
* This behavior causes issues when running tests on Windows. If the file is
|
||||
* not closed, the testSave test will fail due to Access Denied. The
|
||||
* auto-reload test also fails from Windows not triggering file change
|
||||
* notification because the file isn't actually closed by QTemporaryFile.
|
||||
*
|
||||
* This class isolates the Windows specific logic that uses QFile to really
|
||||
* close the test file when requested to.
|
||||
*/
|
||||
class TemporaryFile : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
#ifdef Q_OS_WIN
|
||||
~TemporaryFile();
|
||||
#endif
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
qint64 write(const char* data, qint64 maxSize);
|
||||
qint64 write(const QByteArray& byteArray);
|
||||
|
||||
QString fileName() const;
|
||||
QString filePath() const;
|
||||
|
||||
private:
|
||||
QTemporaryFile m_tempFile;
|
||||
#ifdef Q_OS_WIN
|
||||
QFile m_file;
|
||||
static const QString SUFFIX;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_TEMPORARYFILE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,17 +19,19 @@
|
||||
#ifndef KEEPASSX_TESTGUI_H
|
||||
#define KEEPASSX_TESTGUI_H
|
||||
|
||||
#include "TemporaryFile.h"
|
||||
#include "gui/MainWindow.h"
|
||||
#include "util/TemporaryFile.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QScopedPointer>
|
||||
#include <QSharedPointer>
|
||||
|
||||
class Database;
|
||||
class DatabaseTabWidget;
|
||||
class DatabaseWidget;
|
||||
class QAbstractItemView;
|
||||
class MainWindow;
|
||||
|
||||
class TestGui : public QObject
|
||||
{
|
||||
@@ -84,12 +86,12 @@ private:
|
||||
Qt::MouseButton button,
|
||||
Qt::KeyboardModifiers stateKey = 0);
|
||||
|
||||
QPointer<MainWindow> m_mainWindow;
|
||||
QScopedPointer<MainWindow> m_mainWindow;
|
||||
QPointer<DatabaseTabWidget> m_tabWidget;
|
||||
QPointer<DatabaseWidget> m_dbWidget;
|
||||
QPointer<Database> m_db;
|
||||
QSharedPointer<Database> m_db;
|
||||
QByteArray m_dbData;
|
||||
TemporaryFile m_dbFile;
|
||||
QScopedPointer<TemporaryFile> m_dbFile;
|
||||
QString m_dbFileName;
|
||||
QString m_dbFilePath;
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
*/
|
||||
|
||||
#include "MockChallengeResponseKey.h"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifndef KEEPASSXC_MOCKCHALLENGERESPONSEKEY_H
|
||||
#define KEEPASSXC_MOCKCHALLENGERESPONSEKEY_H
|
||||
|
||||
@@ -15,72 +15,72 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TestClock.h"
|
||||
#include "MockClock.h"
|
||||
|
||||
TestClock::TestClock(int year, int month, int day, int hour, int min, int second)
|
||||
MockClock::MockClock(int year, int month, int day, int hour, int min, int second)
|
||||
: Clock()
|
||||
, m_utcCurrent(datetimeUtc(year, month, day, hour, min, second))
|
||||
{
|
||||
}
|
||||
|
||||
TestClock::TestClock(QDateTime utcBase)
|
||||
MockClock::MockClock(QDateTime utcBase)
|
||||
: Clock()
|
||||
, m_utcCurrent(utcBase)
|
||||
{
|
||||
}
|
||||
|
||||
const QDateTime& TestClock::advanceSecond(int seconds)
|
||||
const QDateTime& MockClock::advanceSecond(int seconds)
|
||||
{
|
||||
m_utcCurrent = m_utcCurrent.addSecs(seconds);
|
||||
return m_utcCurrent;
|
||||
}
|
||||
|
||||
const QDateTime& TestClock::advanceMinute(int minutes)
|
||||
const QDateTime& MockClock::advanceMinute(int minutes)
|
||||
{
|
||||
m_utcCurrent = m_utcCurrent.addSecs(minutes * 60);
|
||||
return m_utcCurrent;
|
||||
}
|
||||
|
||||
const QDateTime& TestClock::advanceHour(int hours)
|
||||
const QDateTime& MockClock::advanceHour(int hours)
|
||||
{
|
||||
m_utcCurrent = m_utcCurrent.addSecs(hours * 60 * 60);
|
||||
return m_utcCurrent;
|
||||
}
|
||||
|
||||
const QDateTime& TestClock::advanceDay(int days)
|
||||
const QDateTime& MockClock::advanceDay(int days)
|
||||
{
|
||||
m_utcCurrent = m_utcCurrent.addDays(days);
|
||||
return m_utcCurrent;
|
||||
}
|
||||
|
||||
const QDateTime& TestClock::advanceMonth(int months)
|
||||
const QDateTime& MockClock::advanceMonth(int months)
|
||||
{
|
||||
m_utcCurrent = m_utcCurrent.addMonths(months);
|
||||
return m_utcCurrent;
|
||||
}
|
||||
|
||||
const QDateTime& TestClock::advanceYear(int years)
|
||||
const QDateTime& MockClock::advanceYear(int years)
|
||||
{
|
||||
m_utcCurrent = m_utcCurrent.addYears(years);
|
||||
return m_utcCurrent;
|
||||
}
|
||||
|
||||
void TestClock::setup(Clock* clock)
|
||||
void MockClock::setup(Clock* clock)
|
||||
{
|
||||
Clock::setInstance(clock);
|
||||
}
|
||||
|
||||
void TestClock::teardown()
|
||||
void MockClock::teardown()
|
||||
{
|
||||
Clock::resetInstance();
|
||||
}
|
||||
|
||||
QDateTime TestClock::currentDateTimeUtcImpl() const
|
||||
QDateTime MockClock::currentDateTimeUtcImpl() const
|
||||
{
|
||||
return m_utcCurrent;
|
||||
}
|
||||
|
||||
QDateTime TestClock::currentDateTimeImpl() const
|
||||
QDateTime MockClock::currentDateTimeImpl() const
|
||||
{
|
||||
return m_utcCurrent.toLocalTime();
|
||||
}
|
||||
@@ -22,12 +22,12 @@
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
class TestClock : public Clock
|
||||
class MockClock : public Clock
|
||||
{
|
||||
public:
|
||||
TestClock(int year, int month, int day, int hour, int min, int second);
|
||||
MockClock(int year, int month, int day, int hour, int min, int second);
|
||||
|
||||
TestClock(QDateTime utcBase = QDateTime::currentDateTimeUtc());
|
||||
MockClock(QDateTime utcBase = QDateTime::currentDateTimeUtc());
|
||||
|
||||
const QDateTime& advanceSecond(int seconds);
|
||||
const QDateTime& advanceMinute(int minutes);
|
||||
55
tests/util/TemporaryFile.cpp
Normal file
55
tests/util/TemporaryFile.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program 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 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TemporaryFile.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
TemporaryFile::TemporaryFile()
|
||||
: TemporaryFile(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
TemporaryFile::TemporaryFile(const QString& templateName)
|
||||
: TemporaryFile(templateName, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
TemporaryFile::TemporaryFile(QObject* parent)
|
||||
: QFile(parent)
|
||||
{
|
||||
QTemporaryFile tmp;
|
||||
tmp.open();
|
||||
QFile::setFileName(tmp.fileName());
|
||||
tmp.close();
|
||||
}
|
||||
|
||||
TemporaryFile::TemporaryFile(const QString& templateName, QObject* parent)
|
||||
: QFile(parent)
|
||||
{
|
||||
QTemporaryFile tmp(templateName);
|
||||
tmp.open();
|
||||
QFile::setFileName(tmp.fileName());
|
||||
tmp.close();
|
||||
}
|
||||
|
||||
bool TemporaryFile::open()
|
||||
{
|
||||
return QFile::open(QIODevice::ReadWrite);
|
||||
}
|
||||
|
||||
#endif
|
||||
50
tests/util/TemporaryFile.h
Normal file
50
tests/util/TemporaryFile.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program 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 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef KEEPASSXC_TEMPORARYFILE_H
|
||||
#define KEEPASSXC_TEMPORARYFILE_H
|
||||
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
/**
|
||||
* QTemporaryFile does not actually close a file when close() is
|
||||
* called, which causes the file to be locked on Windows.
|
||||
* This class extends a QFile with the extra functionality
|
||||
* of a QTemporaryFile to circumvent this problem.
|
||||
*/
|
||||
class TemporaryFile : public QFile
|
||||
#else
|
||||
class TemporaryFile : public QTemporaryFile
|
||||
#endif
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
public:
|
||||
TemporaryFile();
|
||||
explicit TemporaryFile(const QString& templateName);
|
||||
explicit TemporaryFile(QObject* parent);
|
||||
TemporaryFile(const QString& templateName, QObject* parent);
|
||||
~TemporaryFile() override = default;
|
||||
|
||||
using QFile::open;
|
||||
bool open();
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_TEMPORARYFILE_H
|
||||
Reference in New Issue
Block a user