From 77be4686707685049b0a16f656835bca88bb5aef Mon Sep 17 00:00:00 2001 From: varjolintu Date: Thu, 5 Sep 2019 08:32:32 +0300 Subject: [PATCH] Fix crash when removing custom data --- src/gui/EditWidgetProperties.cpp | 23 ++-- tests/data/NewDatabaseBrowser.kdbx | Bin 0 -> 16743 bytes tests/gui/CMakeLists.txt | 2 +- tests/gui/TestGuiBrowser.cpp | 189 +++++++++++++++++++++++++++++ tests/gui/TestGuiBrowser.h | 65 ++++++++++ 5 files changed, 271 insertions(+), 8 deletions(-) create mode 100644 tests/data/NewDatabaseBrowser.kdbx create mode 100644 tests/gui/TestGuiBrowser.cpp create mode 100644 tests/gui/TestGuiBrowser.h diff --git a/src/gui/EditWidgetProperties.cpp b/src/gui/EditWidgetProperties.cpp index dbaaf4148..84223c840 100644 --- a/src/gui/EditWidgetProperties.cpp +++ b/src/gui/EditWidgetProperties.cpp @@ -71,6 +71,11 @@ void EditWidgetProperties::setCustomData(CustomData* customData) void EditWidgetProperties::removeSelectedPluginData() { + QModelIndexList indexes = m_ui->customDataTable->selectionModel()->selectedRows(0); + if (indexes.isEmpty()) { + return; + } + auto result = MessageBox::question(this, tr("Delete plugin data?"), tr("Do you really want to delete the selected plugin data?\n" @@ -82,14 +87,18 @@ void EditWidgetProperties::removeSelectedPluginData() return; } - const QItemSelectionModel* itemSelectionModel = m_ui->customDataTable->selectionModel(); - if (itemSelectionModel) { - for (const QModelIndex& index : itemSelectionModel->selectedRows(0)) { - const QString key = index.data().toString(); - m_customData->remove(key); - } - update(); + QStringList selectedData; + for (const auto& index : indexes) { + const QString key = index.data().toString(); + selectedData.append(key); } + + std::sort(selectedData.begin(), selectedData.end()); + for (const auto& key : selectedData) { + m_customData->remove(key); + } + + update(); } void EditWidgetProperties::toggleRemoveButton(const QItemSelection& selected) diff --git a/tests/data/NewDatabaseBrowser.kdbx b/tests/data/NewDatabaseBrowser.kdbx new file mode 100644 index 0000000000000000000000000000000000000000..97599fccf2d6b49d19cbf357e931ced5c8c3515f GIT binary patch literal 16743 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¥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 z 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 + * Copyright (C) 2019 KeePassXC Team + * + * 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 . + */ + +#include "TestGuiBrowser.h" +#include "TestGlobal.h" +#include "gui/Application.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config-keepassx-tests.h" +#include "core/Bootstrap.h" +#include "core/Config.h" +#include "core/Database.h" +#include "core/Entry.h" +#include "core/Tools.h" +#include "crypto/Crypto.h" +#include "gui/DatabaseTabWidget.h" +#include "gui/DatabaseWidget.h" +#include "gui/FileDialog.h" +#include "gui/MessageBox.h" +#include "gui/PasswordEdit.h" +#include "gui/dbsettings/DatabaseSettingsDialog.h" +#include "gui/entry/EditEntryWidget.h" +#include "gui/entry/EntryView.h" + +QTEST_MAIN(TestGuiBrowser) + +void TestGuiBrowser::initTestCase() +{ + QVERIFY(Crypto::init()); + Config::createTempFileInstance(); + // Disable autosave so we can test the modified file indicator + config()->set("AutoSaveAfterEveryChange", false); + config()->set("AutoSaveOnExit", false); + // Enable the tray icon so we can test hiding/restoring the windowQByteArray + config()->set("GUI/ShowTrayIcon", true); + // Disable advanced settings mode (activate within individual tests to test advanced settings) + config()->set("GUI/AdvancedSettings", false); + // Disable the update check first time alert + config()->set("UpdateCheckMessageShown", true); + + m_mainWindow.reset(new MainWindow()); + Bootstrap::restoreMainWindowState(*m_mainWindow); + m_tabWidget = m_mainWindow->findChild("tabWidget"); + m_mainWindow->show(); + + // Load the NewDatabase.kdbx file into temporary storage + QFile sourceDbFile(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabaseBrowser.kdbx")); + QVERIFY(sourceDbFile.open(QIODevice::ReadOnly)); + QVERIFY(Tools::readAllFromDevice(&sourceDbFile, m_dbData)); + sourceDbFile.close(); +} + +// Every test starts with opening the temp database +void TestGuiBrowser::init() +{ + m_dbFile.reset(new TemporaryFile()); + // Write the temp storage to a temp database file for use in our tests + QVERIFY(m_dbFile->open()); + QCOMPARE(m_dbFile->write(m_dbData), static_cast((m_dbData.size()))); + m_dbFileName = QFileInfo(m_dbFile->fileName()).fileName(); + m_dbFilePath = m_dbFile->fileName(); + m_dbFile->close(); + + // make sure window is activated or focus tests may fail + m_mainWindow->activateWindow(); + QApplication::processEvents(); + + fileDialog()->setNextFileName(m_dbFilePath); + triggerAction("actionDatabaseOpen"); + + auto* databaseOpenWidget = m_tabWidget->currentDatabaseWidget()->findChild("databaseOpenWidget"); + QVERIFY(databaseOpenWidget); + auto* editPassword = databaseOpenWidget->findChild("editPassword"); + QVERIFY(editPassword); + editPassword->setFocus(); + + QTest::keyClicks(editPassword, "a"); + QTest::keyClick(editPassword, Qt::Key_Enter); + + m_dbWidget = m_tabWidget->currentDatabaseWidget(); + m_db = m_dbWidget->database(); +} + +// Every test ends with closing the temp database without saving +void TestGuiBrowser::cleanup() +{ + // DO NOT save the database + m_db->markAsClean(); + MessageBox::setNextAnswer(MessageBox::No); + triggerAction("actionDatabaseClose"); + QApplication::processEvents(); + MessageBox::setNextAnswer(MessageBox::NoButton); + + if (m_dbWidget) { + delete m_dbWidget; + } + + m_dbFile->remove(); +} + +void TestGuiBrowser::cleanupTestCase() +{ + m_dbFile->remove(); +} + +void TestGuiBrowser::testEntrySettings() +{ + auto* toolBar = m_mainWindow->findChild("toolBar"); + auto* entryView = m_dbWidget->findChild("entryView"); + + entryView->setFocus(); + QVERIFY(entryView->hasFocus()); + + // Select the first entry in the database + QModelIndex entryItem = entryView->model()->index(0, 1); + Entry* entry = entryView->entryFromIndex(entryItem); + clickIndex(entryItem, entryView, Qt::LeftButton); + + auto* entryEditAction = m_mainWindow->findChild("actionEntryEdit"); + QWidget* entryEditWidget = toolBar->widgetForAction(entryEditAction); + QTest::mouseClick(entryEditWidget, Qt::LeftButton); + QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode); + auto* editEntryWidget = m_dbWidget->findChild("editEntryWidget"); + + // Switch to Properties page and select all rows from the custom data table + editEntryWidget->setCurrentPage(4); + auto customDataTableView = editEntryWidget->findChild("customDataTable"); + QVERIFY(customDataTableView); + QTest::mouseClick(customDataTableView, Qt::LeftButton); + QTest::keyClick(customDataTableView, 'a', Qt::ControlModifier); + + // Remove the data + QCOMPARE(entry->customData()->size(), 2); + auto* removeButton = editEntryWidget->findChild("removeCustomDataButton"); + QVERIFY(removeButton); + MessageBox::setNextAnswer(MessageBox::Delete); + QTest::mouseClick(removeButton, Qt::LeftButton); + + // Apply the removal + auto* editEntryWidgetButtonBox = editEntryWidget->findChild("buttonBox"); + QVERIFY(editEntryWidgetButtonBox); + auto* okButton = editEntryWidgetButtonBox->button(QDialogButtonBox::Ok); + QVERIFY(okButton); + QTRY_VERIFY(okButton->isEnabled()); + QTest::mouseClick(okButton, Qt::LeftButton); + QApplication::processEvents(); + + QCOMPARE(entry->customData()->size(), 0); +} + +void TestGuiBrowser::triggerAction(const QString& name) +{ + auto* action = m_mainWindow->findChild(name); + QVERIFY(action); + QVERIFY(action->isEnabled()); + action->trigger(); + QApplication::processEvents(); +} + +void TestGuiBrowser::clickIndex(const QModelIndex& index, + QAbstractItemView* view, + Qt::MouseButton button, + Qt::KeyboardModifiers stateKey) +{ + QTest::mouseClick(view->viewport(), button, stateKey, view->visualRect(index).center()); +} diff --git a/tests/gui/TestGuiBrowser.h b/tests/gui/TestGuiBrowser.h new file mode 100644 index 000000000..e9bab810f --- /dev/null +++ b/tests/gui/TestGuiBrowser.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2019 KeePassXC Team + * + * 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 . + */ + +#ifndef KEEPASSXC_TESTGUIBROWSER_H +#define KEEPASSXC_TESTGUIBROWSER_H + +#include "gui/MainWindow.h" +#include "util/TemporaryFile.h" + +#include +#include +#include +#include +#include + +class Database; +class DatabaseTabWidget; +class DatabaseWidget; +class QAbstractItemView; + +class TestGuiBrowser : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void init(); + void cleanup(); + void cleanupTestCase(); + + void testEntrySettings(); + +private: + void triggerAction(const QString& name); + void clickIndex(const QModelIndex& index, + QAbstractItemView* view, + Qt::MouseButton button, + Qt::KeyboardModifiers stateKey = 0); + + QScopedPointer m_mainWindow; + QPointer m_tabWidget; + QPointer m_dbWidget; + QSharedPointer m_db; + QByteArray m_dbData; + QScopedPointer m_dbFile; + QString m_dbFileName; + QString m_dbFilePath; +}; + +#endif // KEEPASSXC_TESTGUIBROWSER_H