Update checking feature (#2648)

* Check on startup (toggleable setting) and manually
* Option to check for pre-releases (eg, 2.4.0-beta1)
* Only included if WITH_XC_NETWORKING is enabled
This commit is contained in:
Weslly 2019-01-30 12:11:50 -02:00 committed by Jonathan White
parent 5c9b062f13
commit 779b529da2
17 changed files with 677 additions and 5 deletions

View File

@ -61,9 +61,9 @@ if(WITH_XC_ALL)
set(WITH_XC_YUBIKEY ON)
set(WITH_XC_SSHAGENT ON)
set(WITH_XC_KEESHARE ON)
if(APPLE)
set(WITH_XC_TOUCHID ON)
endif()
if(APPLE)
set(WITH_XC_TOUCHID ON)
endif()
endif()
if(WITH_XC_KEESHARE_SECURE)

View File

@ -102,9 +102,7 @@ These steps place the compiled KeePassXC binary inside the `./build/src/` direct
-DWITH_XC_KEESHARE=[ON|OFF] Enable/Disable KeeShare group syncronization extension (default: OFF)
-DWITH_XC_TOUCHID=[ON|OFF] (macOS Only) Enable/Disable Touch ID unlock (default:OFF)
-DWITH_XC_ALL=[ON|OFF] Enable/Disable compiling all plugins above (default: OFF)
-DWITH_XC_KEESHARE_SECURE=[ON|OFF] Enable/Disable KeeShare secure containers, requires libquazip5 (default: OFF)
-DWITH_TESTS=[ON|OFF] Enable/Disable building of unit tests (default: ON)
-DWITH_GUI_TESTS=[ON|OFF] Enable/Disable building of GUI tests (default: OFF)
-DWITH_DEV_BUILD=[ON|OFF] Enable/Disable deprecated method warnings (default: OFF)

View File

@ -257,6 +257,10 @@ else()
list(APPEND keepassx_SOURCES keys/drivers/YubiKey.h keys/drivers/YubiKeyStub.cpp)
endif()
if(WITH_XC_NETWORKING)
list(APPEND keepassx_SOURCES updatecheck/UpdateChecker.cpp gui/UpdateCheckDialog.cpp)
endif()
if(WITH_XC_TOUCHID)
list(APPEND keepassx_SOURCES touchid/TouchID.mm)
endif()

View File

@ -92,6 +92,7 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
// clang-format on
#ifndef WITH_XC_NETWORKING
m_generalUi->checkForUpdatesOnStartupCheckBox->setVisible(false);
m_secUi->privacy->setVisible(false);
#endif
@ -174,6 +175,8 @@ void ApplicationSettingsWidget::loadSettings()
m_generalUi->systrayMinimizeToTrayCheckBox->setChecked(config()->get("GUI/MinimizeToTray").toBool());
m_generalUi->minimizeOnCloseCheckBox->setChecked(config()->get("GUI/MinimizeOnClose").toBool());
m_generalUi->systrayMinimizeOnStartup->setChecked(config()->get("GUI/MinimizeOnStartup").toBool());
m_generalUi->checkForUpdatesOnStartupCheckBox->setChecked(config()->get("GUI/CheckForUpdates").toBool());
m_generalUi->checkForUpdatesIncludeBetasCheckBox->setChecked(config()->get("GUI/CheckForUpdatesIncludeBetas").toBool());
m_generalUi->autoTypeAskCheckBox->setChecked(config()->get("security/autotypeask").toBool());
if (autoType()->isAvailable()) {
@ -256,6 +259,8 @@ void ApplicationSettingsWidget::saveSettings()
config()->set("GUI/MinimizeToTray", m_generalUi->systrayMinimizeToTrayCheckBox->isChecked());
config()->set("GUI/MinimizeOnClose", m_generalUi->minimizeOnCloseCheckBox->isChecked());
config()->set("GUI/MinimizeOnStartup", m_generalUi->systrayMinimizeOnStartup->isChecked());
config()->set("GUI/CheckForUpdates", m_generalUi->checkForUpdatesOnStartupCheckBox->isChecked());
config()->set("GUI/CheckForUpdatesIncludeBetas", m_generalUi->checkForUpdatesIncludeBetasCheckBox->isChecked());
config()->set("security/autotypeask", m_generalUi->autoTypeAskCheckBox->isChecked());

View File

@ -83,6 +83,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkForUpdatesOnStartupCheckBox">
<property name="text">
<string>Check for updates at application startup</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -179,6 +186,13 @@
<string>General</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QCheckBox" name="checkForUpdatesIncludeBetasCheckBox">
<property name="text">
<string>Include pre-releases when checking for updates</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toolbarHideCheckBox">
<property name="text">

View File

@ -41,6 +41,12 @@
#include "keys/FileKey.h"
#include "keys/PasswordKey.h"
#ifdef WITH_XC_NETWORKING
#include "updatecheck/UpdateChecker.h"
#include "gui/MessageBox.h"
#include "gui/UpdateCheckDialog.h"
#endif
#ifdef WITH_XC_SSHAGENT
#include "sshagent/AgentSettingsPage.h"
#include "sshagent/SSHAgent.h"
@ -282,6 +288,7 @@ MainWindow::MainWindow()
m_ui->actionPasswordGenerator->setIcon(filePath()->icon("actions", "password-generator"));
m_ui->actionAbout->setIcon(filePath()->icon("actions", "help-about"));
m_ui->actionCheckForUpdates->setIcon(filePath()->icon("actions", "system-software-update"));
m_actionMultiplexer.connect(
SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(setMenuActionState(DatabaseWidget::Mode)));
@ -364,6 +371,15 @@ MainWindow::MainWindow()
#ifdef Q_OS_MACOS
setUnifiedTitleAndToolBarOnMac(true);
#endif
#ifdef WITH_XC_NETWORKING
connect(m_ui->actionCheckForUpdates, SIGNAL(triggered()), SLOT(showUpdateCheckDialog()));
connect(UpdateChecker::instance(), SIGNAL(updateCheckFinished(bool, QString, bool)), SLOT(hasUpdateAvailable(bool, QString, bool)));
QTimer::singleShot(3000, this, SLOT(showUpdateCheckStartup()));
#else
m_ui->actionCheckForUpdates->setVisible(false);
#endif
// clang-format off
connect(m_ui->tabWidget,
SIGNAL(messageGlobal(QString,MessageWidget::MessageType)),
@ -661,6 +677,48 @@ void MainWindow::showAboutDialog()
aboutDialog->open();
}
void MainWindow::showUpdateCheckStartup()
{
#ifdef WITH_XC_NETWORKING
if (!config()->get("UpdateCheckMessageShown", false).toBool()) {
auto result = MessageBox::question(this,
tr("Check for updates on startup?"),
tr("Would you like KeePassXC to check for updates on startup?") + "\n\n" +
tr("You can always check for updates manually from the application menu."),
MessageBox::Yes | MessageBox::No,
MessageBox::Yes);
config()->set("GUI/CheckForUpdates", (result == MessageBox::Yes));
config()->set("UpdateCheckMessageShown", true);
}
if (config()->get("GUI/CheckForUpdates", false).toBool()) {
updateCheck()->checkForUpdates(false);
}
#endif
}
void MainWindow::hasUpdateAvailable(bool hasUpdate, const QString& version, bool isManuallyRequested)
{
#ifdef WITH_XC_NETWORKING
if (hasUpdate && !isManuallyRequested) {
auto* updateCheckDialog = new UpdateCheckDialog(this);
updateCheckDialog->showUpdateCheckResponse(hasUpdate, version);
updateCheckDialog->show();
}
#endif
}
void MainWindow::showUpdateCheckDialog()
{
#ifdef WITH_XC_NETWORKING
updateCheck()->checkForUpdates(true);
auto* updateCheckDialog = new UpdateCheckDialog(this);
updateCheckDialog->show();
#endif
}
void MainWindow::openDonateUrl()
{
QDesktopServices::openUrl(QUrl("https://keepassxc.org/donate"));

View File

@ -83,6 +83,9 @@ private slots:
void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::Mode::None);
void updateWindowTitle();
void showAboutDialog();
void showUpdateCheckStartup();
void showUpdateCheckDialog();
void hasUpdateAvailable(bool hasUpdate, const QString& version, bool isManuallyRequested);
void openDonateUrl();
void openBugReportUrl();
void switchToDatabases();

View File

@ -223,6 +223,7 @@
<string>&amp;Help</string>
</property>
<addaction name="actionAbout"/>
<addaction name="actionCheckForUpdates"/>
<addaction name="actionDonate"/>
<addaction name="actionBugReport"/>
</widget>
@ -348,6 +349,14 @@
<enum>QAction::AboutRole</enum>
</property>
</action>
<action name="actionCheckForUpdates">
<property name="text">
<string>Check for Updates...</string>
</property>
<property name="menuRole">
<enum>QAction::ApplicationSpecificRole</enum>
</property>
</action>
<action name="actionDatabaseOpen">
<property name="text">
<string>&amp;Open database...</string>

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2019 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 "UpdateCheckDialog.h"
#include "ui_UpdateCheckDialog.h"
#include "updatecheck/UpdateChecker.h"
#include "core/FilePath.h"
UpdateCheckDialog::UpdateCheckDialog(QWidget* parent)
: QDialog(parent)
, m_ui(new Ui::UpdateCheckDialog())
{
m_ui->setupUi(this);
setWindowFlags(Qt::Window);
setAttribute(Qt::WA_DeleteOnClose);
m_ui->iconLabel->setPixmap(filePath()->applicationIcon().pixmap(48));
connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close()));
connect(UpdateChecker::instance(), SIGNAL(updateCheckFinished(bool, QString, bool)), SLOT(showUpdateCheckResponse(bool, QString)));
}
void UpdateCheckDialog::showUpdateCheckResponse(bool status, const QString& version) {
m_ui->progressBar->setVisible(false);
m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close"));
if (version == QString("error")) {
setWindowTitle(tr("Update Error!"));
m_ui->statusLabel->setText(
"<strong>" + tr("Update Error!") + "</strong><br><br>" +
tr("An error occurred in retrieving update information.") + "<br>" +
tr("Please try again later."));
return;
}
if (status) {
setWindowTitle(tr("Software Update"));
m_ui->statusLabel->setText(
"<strong>" + tr("A new version of KeePassXC is available!") + "</strong><br><br>" +
tr("KeePassXC %1 is now available — you have %2.").arg(version, KEEPASSXC_VERSION) + "<br><br>" +
"<a href='https://keepassxc.org/download/'>" +
tr("Download it at keepassxc.org") +
"</a>");
} else {
setWindowTitle(tr("You're up-to-date!"));
m_ui->statusLabel->setText(tr(
"KeePassXC %1 is currently the newest version available").arg(KEEPASSXC_VERSION));
}
}
UpdateCheckDialog::~UpdateCheckDialog()
{
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2019 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_UPDATECHECKDIALOG_H
#define KEEPASSXC_UPDATECHECKDIALOG_H
#include <QUrl>
#include <QDialog>
#include <QScopedPointer>
#include "gui/MessageBox.h"
#include "config-keepassx.h"
#include "core/Global.h"
#include "updatecheck/UpdateChecker.h"
namespace Ui
{
class UpdateCheckDialog;
}
class UpdateCheckDialog : public QDialog
{
Q_OBJECT
public:
explicit UpdateCheckDialog(QWidget* parent = nullptr);
~UpdateCheckDialog() override;
public slots:
void showUpdateCheckResponse(bool status, const QString& version);
private:
QScopedPointer<Ui::UpdateCheckDialog> m_ui;
};
#endif //KEEPASSXC_UPDATECHECKDIALOG_H

View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UpdateCheckDialog</class>
<widget class="QDialog" name="UpdateCheckDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>375</width>
<height>136</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="windowTitle">
<string>Checking for updates</string>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>16</number>
</property>
<property name="rightMargin">
<number>16</number>
</property>
<property name="bottomMargin">
<number>16</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="iconLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>60</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignHCenter|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="statusLabel">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Checking for updates...</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>UpdateCheckDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>UpdateCheckDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,148 @@
/*
* Copyright (C) 2019 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 "UpdateChecker.h"
#include "core/Config.h"
#include "config-keepassx.h"
#include <QJsonObject>
#include <QtNetwork>
#include <QNetworkAccessManager>
UpdateChecker* UpdateChecker::m_instance(nullptr);
UpdateChecker::UpdateChecker(QObject* parent)
: QObject(parent)
, m_netMgr(new QNetworkAccessManager(this))
, m_reply(nullptr)
{
}
UpdateChecker::~UpdateChecker()
{
}
void UpdateChecker::checkForUpdates(bool manuallyRequested)
{
m_isManuallyRequested = manuallyRequested;
m_bytesReceived.clear();
QString apiUrlStr = QString("https://api.github.com/repos/keepassxreboot/keepassxc/releases");
if (!config()->get("GUI/CheckForUpdatesIncludeBetas", false).toBool()) {
apiUrlStr += "/latest";
}
QUrl apiUrl = QUrl(apiUrlStr);
QNetworkRequest request(apiUrl);
request.setRawHeader("Accept", "application/json");
m_reply = m_netMgr->get(request);
connect(m_reply, &QNetworkReply::finished, this, &UpdateChecker::fetchFinished);
connect(m_reply, &QIODevice::readyRead, this, &UpdateChecker::fetchReadyRead);
}
void UpdateChecker::fetchReadyRead()
{
m_bytesReceived += m_reply->readAll();
}
void UpdateChecker::fetchFinished()
{
bool error = (m_reply->error() != QNetworkReply::NoError);
bool hasNewVersion = false;
QUrl url = m_reply->url();
QString version = "";
m_reply->deleteLater();
m_reply = nullptr;
if (!error) {
QJsonDocument jsonResponse = QJsonDocument::fromJson(m_bytesReceived);
QJsonObject jsonObject = jsonResponse.object();
if (config()->get("GUI/CheckForUpdatesIncludeBetas", false).toBool()) {
QJsonArray jsonArray = jsonResponse.array();
jsonObject = jsonArray.at(0).toObject();
}
if (!jsonObject.value("tag_name").isUndefined()) {
version = jsonObject.value("tag_name").toString();
hasNewVersion = compareVersions(version, QString(KEEPASSXC_VERSION));
}
} else {
version = "error";
}
emit updateCheckFinished(hasNewVersion, version, m_isManuallyRequested);
}
bool UpdateChecker::compareVersions(const QString& remoteVersion, const QString& localVersion)
{
if (localVersion == remoteVersion) {
return false; // Currently using updated version
}
QRegularExpression verRegex("^(\\d+(\\.\\d+){0,2})(-\\w+)?$", QRegularExpression::CaseInsensitiveOption);
QRegularExpressionMatch lmatch = verRegex.match(localVersion);
QRegularExpressionMatch rmatch = verRegex.match(remoteVersion);
if (!lmatch.captured(1).isNull() && !rmatch.captured(1).isNull()) {
if (lmatch.captured(1) == rmatch.captured(1) && !lmatch.captured(3).isNull()) {
// Same version, but installed version has snapshot/beta suffix and should be updated to stable
return true;
}
QStringList lparts = lmatch.captured(1).split(".");
QStringList rparts = rmatch.captured(1).split(".");
if (lparts.length() < 3)
lparts << "0";
if (rparts.length() < 3)
rparts << "0";
for (int i = 0; i < 3; i++) {
int l = lparts[i].toInt();
int r = rparts[i].toInt();
if (l == r)
continue;
if (l > r) {
return false; // Installed version is newer than release
} else {
return true; // Installed version is outdated
}
}
return false; // Installed version is the same
}
return false; // Invalid version string
}
UpdateChecker* UpdateChecker::instance()
{
if (!m_instance) {
m_instance = new UpdateChecker();
}
return m_instance;
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2019 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_UPDATECHECK_H
#define KEEPASSXC_UPDATECHECK_H
#include <QString>
#include <QObject>
class QNetworkAccessManager;
class QNetworkReply;
class UpdateChecker : public QObject
{
Q_OBJECT
public:
UpdateChecker(QObject* parent = nullptr);
~UpdateChecker() override;
void checkForUpdates(bool manuallyRequested);
static bool compareVersions(const QString& remoteVersion, const QString& localVersion);
static UpdateChecker* instance();
signals:
void updateCheckFinished(bool hasNewVersion, QString version, bool isManuallyRequested);
private slots:
void fetchFinished();
void fetchReadyRead();
private:
QNetworkAccessManager* m_netMgr;
QNetworkReply* m_reply;
QByteArray m_bytesReceived;
bool m_isManuallyRequested;
static UpdateChecker* m_instance;
Q_DISABLE_COPY(UpdateChecker)
};
inline UpdateChecker* updateCheck()
{
return UpdateChecker::instance();
}
#endif //KEEPASSXC_UPDATECHECK_H

View File

@ -162,6 +162,11 @@ add_unit_test(NAME testkeepass1reader SOURCES TestKeePass1Reader.cpp
add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp
LIBS ${TEST_LIBRARIES})
if(WITH_XC_NETWORKING)
add_unit_test(NAME testupdatecheck SOURCES TestUpdateCheck.cpp
LIBS ${TEST_LIBRARIES})
endif()
if(WITH_XC_AUTOTYPE)
add_unit_test(NAME testautotype SOURCES TestAutoType.cpp
LIBS ${TEST_LIBRARIES})

41
tests/TestUpdateCheck.cpp Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2019 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 "TestUpdateCheck.h"
#include "TestGlobal.h"
#include "updatecheck/UpdateChecker.h"
#include "crypto/Crypto.h"
QTEST_GUILESS_MAIN(TestUpdateCheck)
void TestUpdateCheck::initTestCase()
{
QVERIFY(Crypto::init());
}
void TestUpdateCheck::testCompareVersion()
{
// Remote Version , Installed Version
QCOMPARE(UpdateChecker::compareVersions(QString("2.4.0"), QString("2.3.4")), true);
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.4.0")), false);
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.0")), false);
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.0-beta1")), true);
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0-beta2"), QString("2.3.0-beta1")), true);
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.4"), QString("2.4.0-snapshot")), false);
QCOMPARE(UpdateChecker::compareVersions(QString("invalid"), QString("2.4.0")), false);
QCOMPARE(UpdateChecker::compareVersions(QString(""), QString("2.4.0")), false);
}

32
tests/TestUpdateCheck.h Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2019 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_TESTUPDATECHECK_H
#define KEEPASSX_TESTUPDATECHECK_H
#include <QObject>
class TestUpdateCheck : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void testCompareVersion();
};
#endif // #define KEEPASSX_TESTUPDATECHECK_H

View File

@ -86,6 +86,8 @@ void TestGui::initTestCase()
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);