summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrzysztof Nowicki <[email protected]>2017-10-16 21:45:22 +0200
committerKrzysztof Nowicki <[email protected]>2017-10-16 21:54:23 +0200
commit7c74258355cd91106d7563142177dd7f17801256 (patch)
tree2a5890cda53250bee6daf1bb6058d9675d6b7d51
parent39d5dba11b6b3a7514b7916c71122d4b8a627d84 (diff)
EWS: Refactor server connection and password retrieval
In the old behaviour the resource would attempt to connect to the server at resource construction time, which is not the way it should work. This was a corner cut done in early development, when I was still a novice and I wanted it to just work. As we know cutting corners tends to backfire eventually... The updated implementation connects to the server when the resource is brought online. The password request code also received refactoring. Instead of synchronously waiting for KWallet it now performs the opening asynchronously together with a timeout for safety. A new unit test ensures that the code behaves as designed.
-rw-r--r--resources/ews/ewsconfigdialog.cpp40
-rw-r--r--resources/ews/ewsconfigdialog.h2
-rw-r--r--resources/ews/ewsresource.cpp47
-rw-r--r--resources/ews/ewsresource.h1
-rw-r--r--resources/ews/ewssettings.cpp162
-rw-r--r--resources/ews/ewssettings.h19
-rw-r--r--resources/ews/test/unittests/CMakeLists.txt9
-rw-r--r--resources/ews/test/unittests/ewssettings_ut.cpp692
8 files changed, 892 insertions, 80 deletions
diff --git a/resources/ews/ewsconfigdialog.cpp b/resources/ews/ewsconfigdialog.cpp
index 2912538..be00197 100644
--- a/resources/ews/ewsconfigdialog.cpp
+++ b/resources/ews/ewsconfigdialog.cpp
@@ -51,6 +51,7 @@ static const QVector<StringPair> userAgents = {
EwsConfigDialog::EwsConfigDialog(EwsResource *parentResource, EwsClient &client, WId wId)
: QDialog()
, mParentResource(parentResource)
+ , mSettings(new EwsSettings(wId))
{
if (wId) {
KWindowSystem::setMainWindow(this, wId);
@@ -74,12 +75,12 @@ EwsConfigDialog::EwsConfigDialog(EwsResource *parentResource, EwsClient &client,
mUi->setupUi(mainWidget);
mUi->accountName->setText(parentResource->name());
- mSubWidget = new EwsSubscriptionWidget(client, mParentResource->settings(), this);
+ mSubWidget = new EwsSubscriptionWidget(client, mSettings.data(), this);
mUi->subscriptionTabLayout->addWidget(mSubWidget);
- mConfigManager = new KConfigDialogManager(this, mParentResource->settings());
+ mConfigManager = new KConfigDialogManager(this, mSettings.data());
mConfigManager->updateWidgets();
- switch (mParentResource->settings()->retrievalMethod()) {
+ switch (mSettings->retrievalMethod()) {
case 0:
mUi->pollRadioButton->setChecked(true);
break;
@@ -102,23 +103,24 @@ EwsConfigDialog::EwsConfigDialog(EwsResource *parentResource, EwsClient &client,
mTryConnectNeeded = baseUrlEmpty;
QString password;
- mParentResource->settings()->requestPassword(password, false);
- mUi->passwordEdit->setPassword(password);
+ connect(mSettings.data(), &EwsSettings::passwordRequestFinished, mUi->passwordEdit,
+ &KPasswordLineEdit::setPassword);
+ mSettings->requestPassword(false);
int selectedIndex = -1;
int i = 0;
Q_FOREACH (const StringPair &item, userAgents) {
mUi->userAgentCombo->addItem(item.first, item.second);
- if (mParentResource->settings()->userAgent() == item.second) {
+ if (mSettings->userAgent() == item.second) {
selectedIndex = i;
}
i++;
}
mUi->userAgentCombo->addItem(i18nc("User Agent", "Custom"));
- if (!mParentResource->settings()->userAgent().isEmpty()) {
+ if (!mSettings->userAgent().isEmpty()) {
mUi->userAgentGroupBox->setChecked(true);
mUi->userAgentCombo->setCurrentIndex(selectedIndex >= 0 ? selectedIndex : mUi->userAgentCombo->count() - 1);
- mUi->userAgentEdit->setText(mParentResource->settings()->userAgent());
+ mUi->userAgentEdit->setText(mSettings->userAgent());
} else {
mUi->userAgentCombo->setCurrentIndex(mUi->userAgentCombo->count());
}
@@ -157,32 +159,32 @@ void EwsConfigDialog::save()
mParentResource->setName(mUi->accountName->text());
mConfigManager->updateSettings();
if (mUi->pollRadioButton->isChecked()) {
- mParentResource->settings()->setRetrievalMethod(0);
+ mSettings->setRetrievalMethod(0);
} else {
- mParentResource->settings()->setRetrievalMethod(1);
+ mSettings->setRetrievalMethod(1);
}
/* Erase the subscription id in case subscription is disabled or its parameters changed. This
* fill force creation of a new subscription. */
if (!mSubWidget->subscriptionEnabled() ||
- (mSubWidget->subscribedList() != mParentResource->settings()->serverSubscriptionList())) {
- mParentResource->settings()->setEventSubscriptionId(QString());
- mParentResource->settings()->setEventSubscriptionWatermark(QString());
+ (mSubWidget->subscribedList() != mSettings->serverSubscriptionList())) {
+ mSettings->setEventSubscriptionId(QString());
+ mSettings->setEventSubscriptionWatermark(QString());
}
- mParentResource->settings()->setServerSubscription(mSubWidget->subscriptionEnabled());
+ mSettings->setServerSubscription(mSubWidget->subscriptionEnabled());
if (mSubWidget->subscribedListValid()) {
- mParentResource->settings()->setServerSubscriptionList(mSubWidget->subscribedList());
+ mSettings->setServerSubscriptionList(mSubWidget->subscribedList());
}
if (mUi->userAgentGroupBox->isChecked()) {
- mParentResource->settings()->setUserAgent(mUi->userAgentEdit->text());
+ mSettings->setUserAgent(mUi->userAgentEdit->text());
} else {
- mParentResource->settings()->setUserAgent(QString());
+ mSettings->setUserAgent(QString());
}
- mParentResource->settings()->setPassword(mUi->passwordEdit->password());
- mParentResource->settings()->save();
+ mSettings->setPassword(mUi->passwordEdit->password());
+ mSettings->save();
}
void EwsConfigDialog::performAutoDiscovery()
diff --git a/resources/ews/ewsconfigdialog.h b/resources/ews/ewsconfigdialog.h
index 59d6403..9731198 100644
--- a/resources/ews/ewsconfigdialog.h
+++ b/resources/ews/ewsconfigdialog.h
@@ -36,6 +36,7 @@ class EwsAutodiscoveryJob;
class EwsGetFolderRequest;
class EwsProgressDialog;
class EwsSubscriptionWidget;
+class EwsSettings;
class EwsConfigDialog : public QDialog
{
@@ -69,6 +70,7 @@ private:
bool mTryConnectNeeded = false;
EwsProgressDialog *mProgressDialog = nullptr;
EwsSubscriptionWidget *mSubWidget = nullptr;
+ QScopedPointer<EwsSettings> mSettings;
};
#endif
diff --git a/resources/ews/ewsresource.cpp b/resources/ews/ewsresource.cpp
index d4b652b..008c326 100644
--- a/resources/ews/ewsresource.cpp
+++ b/resources/ews/ewsresource.cpp
@@ -99,14 +99,6 @@ EwsResource::EwsResource(const QString &id)
: Akonadi::ResourceBase(id), mTagsRetrieved(false), mReconnectTimeout(InitialReconnectTimeout),
mSettings(new EwsSettings(winIdForDialogs()))
{
- //setName(i18n("Microsoft Exchange"));
- mEwsClient.setUrl(mSettings->baseUrl());
- mSettings->requestPassword(mPassword, true);
- if (!mSettings->hasDomain()) {
- mEwsClient.setCredentials(mSettings->username(), mPassword);
- } else {
- mEwsClient.setCredentials(mSettings->domain() + QChar::fromLatin1('\\') + mSettings->username(), mPassword);
- }
mEwsClient.setUserAgent(mSettings->userAgent());
mEwsClient.setEnableNTLMv2(mSettings->enableNTLMv2());
@@ -124,13 +116,6 @@ EwsResource::EwsResource(const QString &id)
setScheduleAttributeSyncBeforeItemSync(true);
- if (mSettings->baseUrl().isEmpty()) {
- setOnline(false);
- Q_EMIT status(NotConfigured, i18nc("@info:status", "No server configured yet."));
- } else {
- resetUrl();
- }
-
// Load the sync state
QByteArray data = QByteArray::fromBase64(mSettings->syncState().toAscii());
if (!data.isEmpty()) {
@@ -155,6 +140,9 @@ EwsResource::EwsResource(const QString &id)
QMetaObject::invokeMethod(this, "delayedInit", Qt::QueuedConnection);
connect(this, &AgentBase::reloadConfiguration, this, &EwsResource::reloadConfig);
+
+ connect(mSettings.data(), &EwsSettings::passwordRequestFinished, this,
+ &EwsResource::passwordRequestFinished);
}
EwsResource::~EwsResource()
@@ -461,14 +449,29 @@ void EwsResource::reloadConfig()
{
mSubManager.reset(nullptr);
mEwsClient.setUrl(mSettings->baseUrl());
- mSettings->requestPassword(mPassword, false);
- if (mSettings->domain().isEmpty()) {
- mEwsClient.setCredentials(mSettings->username(), mPassword);
+ mSettings->requestPassword(true);
+}
+
+void EwsResource::passwordRequestFinished(const QString &password)
+{
+ mPassword = password;
+ if (mPassword.isNull()) {
+ setOnline(false);
+ Q_EMIT status(NotConfigured, i18nc("@info:status", "No password configured."));
} else {
- mEwsClient.setCredentials(mSettings->domain() + QChar::fromLatin1('\\') + mSettings->username(), mPassword);
+ if (mSettings->domain().isEmpty()) {
+ mEwsClient.setCredentials(mSettings->username(), mPassword);
+ } else {
+ mEwsClient.setCredentials(mSettings->domain() + QChar::fromLatin1('\\') + mSettings->username(), mPassword);
+ }
+ mSettings->save();
+ if (mSettings->baseUrl().isEmpty()) {
+ setOnline(false);
+ Q_EMIT status(NotConfigured, i18nc("@info:status", "No server configured yet."));
+ } else {
+ resetUrl();
+ }
}
- mSettings->save();
- resetUrl();
}
void EwsResource::configure(WId windowId)
@@ -1248,7 +1251,7 @@ void EwsResource::saveState()
void EwsResource::doSetOnline(bool online)
{
if (online) {
- resetUrl();
+ reloadConfig();
} else {
mSubManager.reset(nullptr);
}
diff --git a/resources/ews/ewsresource.h b/resources/ews/ewsresource.h
index 04e0196..f1b997e 100644
--- a/resources/ews/ewsresource.h
+++ b/resources/ews/ewsresource.h
@@ -144,6 +144,7 @@ private:
void doRetrieveCollections();
int reconnectTimeout();
+ void passwordRequestFinished(const QString &password);
EwsClient mEwsClient;
Akonadi::Collection mRootCollection;
diff --git a/resources/ews/ewssettings.cpp b/resources/ews/ewssettings.cpp
index 216174c..3ad283f 100644
--- a/resources/ews/ewssettings.cpp
+++ b/resources/ews/ewssettings.cpp
@@ -17,83 +17,171 @@
Boston, MA 02110-1301, USA.
*/
-#include <ewssettings.h>
+#include "ewssettings.h"
#include <QPointer>
#include <KPasswordDialog>
#include <KWallet/KWallet>
#include <KLocalizedString>
+#include "ewsresource_debug.h"
+
+static const QString ewsWalletFolder = QStringLiteral("akonadi-ews");
+
+// Allow unittest to override this to shorten test execution
+#ifndef WALLET_TIMEOUT
+#define WALLET_TIMEOUT 30000
+#endif
+
EwsSettings::EwsSettings(WId windowId)
- : EwsSettingsBase(), mWindowId(windowId)
+ : EwsSettingsBase(), mWindowId(windowId), mWalletReadTimer(this), mWalletWriteTimer(this)
{
+ mWalletReadTimer.setInterval(WALLET_TIMEOUT);
+ mWalletReadTimer.setSingleShot(true);
+ connect(&mWalletReadTimer, &QTimer::timeout, this, [this]() {
+ qCWarning(EWSRES_LOG) << "Timeout waiting for wallet open for read";
+ onWalletOpenedForRead(false);
+ });
+ mWalletWriteTimer.setInterval(WALLET_TIMEOUT);
+ mWalletWriteTimer.setSingleShot(true);
+ connect(&mWalletWriteTimer, &QTimer::timeout, this, [this]() {
+ qCWarning(EWSRES_LOG) << "Timeout waiting for wallet open for write";
+ onWalletOpenedForWrite(false);
+ });
}
EwsSettings::~EwsSettings()
{
}
-bool EwsSettings::requestPassword(QString &password, bool ask)
+void EwsSettings::requestPassword(bool ask)
{
- bool status = true;
+ bool status = false;
- if (!mPassword.isEmpty()) {
- password = mPassword;
- return true;
+ qCDebug(EWSRES_LOG) << "requestPassword: start";
+ if (!mPassword.isNull()) {
+ qCDebug(EWSRES_LOG) << "requestPassword: password already set";
+ Q_EMIT passwordRequestFinished(mPassword);
+ return;
}
- QScopedPointer<KWallet::Wallet> wallet(KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(),
- mWindowId));
- if (wallet && wallet->isOpen()) {
- if (wallet->hasFolder(QStringLiteral("akonadi-ews"))) {
- wallet->setFolder(QStringLiteral("akonadi-ews"));
- wallet->readPassword(config()->name(), password);
+ if (!mWallet) {
+ mWallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(),
+ mWindowId, KWallet::Wallet::Asynchronous);
+ if (mWallet) {
+ connect(mWallet.data(), &KWallet::Wallet::walletOpened, this,
+ &EwsSettings::onWalletOpenedForRead);
+ mWalletReadTimer.start();
+ return;
} else {
- wallet->createFolder(QStringLiteral("akonadi-ews"));
+ qCWarning(EWSRES_LOG) << "Failed to open wallet";
}
- } else {
- status = false;
+ }
+ if (mWallet && mWallet->isOpen()) {
+ mPassword = readPassword();
+ mWallet.clear();
+ status = true;
}
if (!status) {
if (!ask) {
- return false;
- }
-
- QPointer<KPasswordDialog> dlg = new KPasswordDialog(nullptr);
- dlg->setModal(true);
- dlg->setPrompt(i18n("Please enter password for user '%1' and Exchange account '%2'.",
- username(), email()));
- dlg->setAttribute(Qt::WA_DeleteOnClose);
- if (dlg->exec() == QDialog::Accepted) {
- password = dlg->password();
- setPassword(password);
+ qCDebug(EWSRES_LOG) << "requestPassword: Not allowed to ask";
} else {
+ qCDebug(EWSRES_LOG) << "requestPassword: Requesting interactively";
+ QPointer<KPasswordDialog> dlg = new KPasswordDialog(nullptr);
+ dlg->setModal(true);
+ dlg->setPrompt(i18n("Please enter password for user '%1' and Exchange account '%2'.",
+ username(), email()));
+ if (dlg->exec() == QDialog::Accepted) {
+ mPassword = dlg->password();
+ setPassword(mPassword);
+ }
delete dlg;
- return false;
}
- delete dlg;
}
- return true;
+ Q_EMIT passwordRequestFinished(mPassword);
+ return;
+}
+
+QString EwsSettings::readPassword() const
+{
+ QString password;
+ if (mWallet->hasFolder(ewsWalletFolder)) {
+ mWallet->setFolder(ewsWalletFolder);
+ mWallet->readPassword(config()->name(), password);
+ } else {
+ mWallet->createFolder(ewsWalletFolder);
+ }
+ return password;
+}
+
+void EwsSettings::onWalletOpenedForRead(bool success)
+{
+ qCDebug(EWSRES_LOG) << "onWalletOpenedForRead: start" << success;
+ mWalletReadTimer.stop();
+ if (mWallet) {
+ if (success) {
+ if (mPassword.isNull()) {
+ mPassword = readPassword();
+ }
+ qCDebug(EWSRES_LOG) << "onWalletOpenedForRead: got password";
+ Q_EMIT passwordRequestFinished(mPassword);
+ } else {
+ qCDebug(EWSRES_LOG) << "onWalletOpenedForRead: failed to retrieve password";
+ Q_EMIT passwordRequestFinished(QString());
+ }
+ mWallet.clear();
+ }
}
void EwsSettings::setPassword(const QString &password)
{
+ if (password.isNull()) {
+ qCWarning(EWSRES_LOG) << "Trying to set a null password";
+ return;
+ }
+
mPassword = password;
- QScopedPointer<KWallet::Wallet> wallet(KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(),
- mWindowId));
- if (wallet && wallet->isOpen()) {
- if (!wallet->hasFolder(QStringLiteral("akonadi-ews"))) {
- wallet->createFolder(QStringLiteral("akonadi-ews"));
+
+ /* If a pending password request is running, satisfy it. */
+ if (mWallet) {
+ onWalletOpenedForRead(true);
+ }
+
+ mWallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(),
+ mWindowId, KWallet::Wallet::Asynchronous);
+ if (mWallet) {
+ connect(mWallet.data(), &KWallet::Wallet::walletOpened, this, &EwsSettings::onWalletOpenedForWrite);
+ mWalletWriteTimer.start();
+ } else {
+ qCWarning(EWSRES_LOG) << "Failed to open wallet";
+ }
+}
+
+void EwsSettings::onWalletOpenedForWrite(bool success)
+{
+ mWalletWriteTimer.stop();
+ if (success) {
+ if (!mWallet->hasFolder(ewsWalletFolder)) {
+ mWallet->createFolder(ewsWalletFolder);
}
- wallet->setFolder(QStringLiteral("akonadi-ews"));
- wallet->writePassword(config()->name(), password);
+ mWallet->setFolder(ewsWalletFolder);
+ mWallet->writePassword(config()->name(), mPassword);
}
+ mWallet.clear();
}
void EwsSettings::setTestPassword(const QString &password)
{
+ if (password.isNull()) {
+ qCWarning(EWSRES_LOG) << "Trying to set a null password";
+ return;
+ }
+
mPassword = password;
+ if (mWallet) {
+ onWalletOpenedForRead(true);
+ }
}
diff --git a/resources/ews/ewssettings.h b/resources/ews/ewssettings.h
index aae96a2..a4600f7 100644
--- a/resources/ews/ewssettings.h
+++ b/resources/ews/ewssettings.h
@@ -22,6 +22,13 @@
#include "ewssettingsbase.h"
+#include <QTimer>
+#include <QPointer>
+
+namespace KWallet {
+class Wallet;
+}
+
class EwsSettings : public EwsSettingsBase
{
Q_OBJECT
@@ -30,14 +37,22 @@ public:
explicit EwsSettings(WId windowId);
~EwsSettings() override;
- bool requestPassword(QString &password, bool ask);
+ void requestPassword(bool ask);
public Q_SLOTS:
Q_SCRIPTABLE void setPassword(const QString &password);
Q_SCRIPTABLE void setTestPassword(const QString &password);
-
+Q_SIGNALS:
+ void passwordRequestFinished(const QString &password);
+private Q_SLOTS:
+ void onWalletOpenedForRead(bool success);
+ void onWalletOpenedForWrite(bool success);
private:
+ QString readPassword() const;
WId mWindowId;
QString mPassword;
+ QPointer<KWallet::Wallet> mWallet;
+ QTimer mWalletReadTimer;
+ QTimer mWalletWriteTimer;
};
#endif
diff --git a/resources/ews/test/unittests/CMakeLists.txt b/resources/ews/test/unittests/CMakeLists.txt
index b74c717..9443e05 100644
--- a/resources/ews/test/unittests/CMakeLists.txt
+++ b/resources/ews/test/unittests/CMakeLists.txt
@@ -33,4 +33,13 @@ akonadi_ews_add_ut(ewsgetitemrequest_ut)
akonadi_ews_add_ut(ewsunsubscriberequest_ut)
akonadi_ews_add_ut(ewsattachment_ut)
+add_executable(ewssettings_ut
+ ewssettings_ut.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../ewssettings.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/../../ewssettingsbase.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/../../ewsres_debug.cpp)
+target_link_libraries(ewssettings_ut Qt5::Core Qt5::Test KF5::WidgetsAddons KF5::I18n KF5::ConfigCore KF5::ConfigGui KF5::Wallet)
+target_compile_definitions(ewssettings_ut PUBLIC -DWALLET_TIMEOUT=2000)
+add_test(NAME ewssettings_ut COMMAND ewssettings_ut)
+
diff --git a/resources/ews/test/unittests/ewssettings_ut.cpp b/resources/ews/test/unittests/ewssettings_ut.cpp
new file mode 100644
index 0000000..c4899fc
--- /dev/null
+++ b/resources/ews/test/unittests/ewssettings_ut.cpp
@@ -0,0 +1,692 @@
+/*
+ Copyright (C) 2017 Krzysztof Nowicki <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <functional>
+#include <QtTest>
+#include <KWallet/KWallet>
+
+#include "ewssettings.h"
+
+class UtEwsSettings : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void readNoPassword();
+ void readNullWallet();
+ void readTimeout();
+ void readTimeoutInterrupted();
+ void readValidPassword();
+ void writeNullPassword();
+ void writeNullWallet();
+ void writeTimeout();
+ void writeValidPassword();
+};
+
+namespace KWallet {
+
+class MyWallet : public Wallet
+{
+ Q_OBJECT
+public:
+ MyWallet();
+ ~MyWallet() override;
+
+ void doOpen(bool success);
+
+ bool hasFolder(const QString &folder) override;
+ bool setFolder(const QString &folder) override;
+ bool createFolder(const QString &folder) override;
+ int readPassword(const QString &key, QString &value) override;
+ int writePassword(const QString &key, const QString &value) override;
+
+ std::function<bool(const QString &)> hasFolderCallback;
+ std::function<bool(const QString &)> setFolderCallback;
+ std::function<bool(const QString &)> createFolderCallback;
+ std::function<int(const QString &, QString &)> readPasswordCallback;
+ std::function<int(const QString &, const QString &)> writePasswordCallback;
+};
+
+static std::function<void()> errorCallback;
+static std::function<Wallet*(MyWallet *wallet)> openWalletCallback;
+
+void reportError()
+{
+ if (errorCallback) {
+ errorCallback();
+ }
+}
+
+Wallet *openWallet(MyWallet *wallet)
+{
+ if (openWalletCallback) {
+ return openWalletCallback(wallet);
+ } else {
+ qDebug() << "Wallet open callback not registered!";
+ errorCallback();
+ return wallet;
+ }
+}
+
+static const QString networkWallet = QStringLiteral("test_network_wallet");
+const QString Wallet::NetworkWallet()
+{
+ return networkWallet;
+}
+
+Wallet *Wallet::openWallet(const QString &name, WId, OpenType ot)
+{
+ qDebug() << "intercepted openWallet";
+ if (name != networkWallet) {
+ qDebug() << "Incorrect wallet name";
+ reportError();
+ }
+
+ if (ot != Asynchronous) {
+ qDebug() << "Unsopported open type";
+ reportError();
+ }
+
+ auto wallet = new MyWallet();
+ return KWallet::openWallet(wallet);
+}
+
+MyWallet::MyWallet()
+ : Wallet(0, networkWallet)
+{
+
+}
+
+MyWallet::~MyWallet()
+{
+}
+
+void MyWallet::doOpen(bool success)
+{
+ Q_EMIT walletOpened(success);
+}
+
+bool MyWallet::hasFolder(const QString &folder)
+{
+ if (hasFolderCallback) {
+ return hasFolderCallback(folder);
+ } else {
+ qWarning() << "hasFolder() callback not set!";
+ reportError();
+ return false;
+ }
+}
+
+bool MyWallet::setFolder(const QString &folder)
+{
+ if (setFolderCallback) {
+ return setFolderCallback(folder);
+ } else {
+ qWarning() << "setFolder() callback not set!";
+ reportError();
+ return false;
+ }
+}
+
+bool MyWallet::createFolder(const QString &folder)
+{
+ if (createFolderCallback) {
+ return createFolderCallback(folder);
+ } else {
+ qWarning() << "createFolder() callback not set!";
+ reportError();
+ return false;
+ }
+}
+
+int MyWallet::readPassword(const QString &key, QString &value)
+{
+ if (readPasswordCallback) {
+ return readPasswordCallback(key, value);
+ } else {
+ qWarning() << "readPasswordCallback() callback not set!";
+ reportError();
+ return 0;
+ }
+}
+
+int MyWallet::writePassword(const QString &key, const QString &value)
+{
+ if (writePasswordCallback) {
+ return writePasswordCallback(key, value);
+ } else {
+ qWarning() << "writePasswordCallback() callback not set!";
+ reportError();
+ return 0;
+ }
+}
+
+}
+
+void UtEwsSettings::readNoPassword()
+{
+ KWallet::MyWallet *wallet = nullptr;
+ KWallet::openWalletCallback = [&wallet](KWallet::MyWallet *w) {
+ wallet = w;
+ return w;
+ };
+
+ QEventLoop loop;
+ bool error = false;
+ KWallet::errorCallback = [&]() {
+ if (loop.isRunning()) {
+ loop.exit(1);
+ } else {
+ error = true;
+ }
+ };
+
+
+ bool hasFolderCalled = false;
+ QString password;
+ EwsSettings settings(0);
+ connect(&settings, &EwsSettings::passwordRequestFinished, this, [&](const QString &p) {
+ password = p;
+ loop.exit(0);
+ });
+ QTimer::singleShot(100, [&]() {
+ settings.requestPassword(false);
+ if (!wallet) {
+ qDebug() << "Wallet is null";
+ loop.exit(1);
+ return;
+ }
+ wallet->hasFolderCallback = [&hasFolderCalled](const QString &) {
+ hasFolderCalled = true;
+ return false;
+ };
+ wallet->createFolderCallback = [](const QString &) {
+ return false;
+ };
+ wallet->doOpen(true);
+ });
+ QTimer timeoutTimer;
+ connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
+ qDebug() << "Test timeout";
+ loop.exit(1);
+ });
+ timeoutTimer.setSingleShot(true);
+ timeoutTimer.start(2000);
+
+ QVERIFY(error != true);
+
+ QVERIFY(loop.exec() == 0);
+
+ QVERIFY(password.isNull());
+ QVERIFY(hasFolderCalled);
+}
+
+void UtEwsSettings::readNullWallet()
+{
+ KWallet::MyWallet *wallet = nullptr;
+ KWallet::openWalletCallback = [&wallet](KWallet::MyWallet *) {
+ return nullptr;
+ };
+
+ QEventLoop loop;
+ bool error = false;
+ KWallet::errorCallback = [&]() {
+ if (loop.isRunning()) {
+ loop.exit(1);
+ } else {
+ error = true;
+ }
+ };
+
+ QString password;
+ EwsSettings settings(0);
+ connect(&settings, &EwsSettings::passwordRequestFinished, this, [&](const QString &p) {
+ password = p;
+ loop.exit(0);
+ });
+ QTimer::singleShot(100, [&]() {
+ settings.requestPassword(false);
+ });
+ QTimer timeoutTimer;
+ connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
+ qDebug() << "Test timeout";
+ loop.exit(1);
+ });
+ timeoutTimer.setSingleShot(true);
+ timeoutTimer.start(2000);
+
+
+ QVERIFY(error != true);
+
+ QVERIFY(loop.exec() == 0);
+
+ QVERIFY(password.isNull());
+}
+
+void UtEwsSettings::readTimeout()
+{
+ KWallet::MyWallet *wallet = nullptr;
+ KWallet::openWalletCallback = [&wallet](KWallet::MyWallet *w) {
+ wallet = w;
+ return w;
+ };
+
+ QEventLoop loop;
+ bool error = false;
+ KWallet::errorCallback = [&]() {
+ if (loop.isRunning()) {
+ loop.exit(1);
+ } else {
+ error = true;
+ }
+ };
+
+
+ bool hasFolderCalled = false;
+ QString password;
+ EwsSettings settings(0);
+ connect(&settings, &EwsSettings::passwordRequestFinished, this, [&](const QString &p) {
+ password = p;
+ loop.exit(0);
+ });
+ QTimer::singleShot(100, [&]() {
+ settings.requestPassword(false);
+ if (!wallet) {
+ qDebug() << "Wallet is null";
+ loop.exit(1);
+ return;
+ }
+ wallet->hasFolderCallback = [&hasFolderCalled](const QString &) {
+ hasFolderCalled = true;
+ return false;
+ };
+ wallet->createFolderCallback = [](const QString &) {
+ return false;
+ };
+ });
+ QTimer timeoutTimer;
+ connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
+ qDebug() << "Test timeout";
+ loop.exit(1);
+ });
+ timeoutTimer.setSingleShot(true);
+ timeoutTimer.start(5000);
+
+ QVERIFY(error != true);
+
+ QVERIFY(loop.exec() == 0);
+
+ QVERIFY(password.isNull());
+ QVERIFY(!hasFolderCalled);
+}
+
+void UtEwsSettings::readTimeoutInterrupted()
+{
+ KWallet::MyWallet *wallet = nullptr;
+ KWallet::openWalletCallback = [&wallet](KWallet::MyWallet *w) {
+ wallet = w;
+ return w;
+ };
+
+ QEventLoop loop;
+ bool error = false;
+ KWallet::errorCallback = [&]() {
+ if (loop.isRunning()) {
+ loop.exit(1);
+ } else {
+ error = true;
+ }
+ };
+
+
+ bool hasFolderCalled = false;
+ QString password;
+ EwsSettings settings(0);
+ bool testSecondSignal = false;
+ connect(&settings, &EwsSettings::passwordRequestFinished, this, [&](const QString &p) {
+ if (!testSecondSignal) {
+ password = p;
+ loop.exit(0);
+ } else {
+ loop.exit(1);
+ }
+ });
+ QTimer::singleShot(100, [&]() {
+ settings.requestPassword(false);
+ if (!wallet) {
+ qDebug() << "Wallet is null";
+ loop.exit(1);
+ return;
+ }
+ wallet->hasFolderCallback = [&hasFolderCalled](const QString &) {
+ hasFolderCalled = true;
+ return false;
+ };
+ wallet->createFolderCallback = [](const QString &) {
+ return false;
+ };
+ });
+ QTimer::singleShot(1000, [&]() {
+ settings.setTestPassword(QStringLiteral("foo"));
+ });
+ QTimer timeoutTimer;
+ connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
+ qDebug() << "Test timeout";
+ loop.exit(2);
+ });
+ timeoutTimer.setSingleShot(true);
+ timeoutTimer.start(5000);
+
+ QVERIFY(error != true);
+
+ QVERIFY(loop.exec() == 0);
+
+ QVERIFY(password == QStringLiteral("foo"));
+ QVERIFY(!hasFolderCalled);
+
+ // Check for second passwordRequestFinished signal
+ QVERIFY(loop.exec() == 2);
+}
+
+void UtEwsSettings::readValidPassword()
+{
+ KWallet::MyWallet *wallet = nullptr;
+ KWallet::openWalletCallback = [&wallet](KWallet::MyWallet *w) {
+ wallet = w;
+ return w;
+ };
+
+ QEventLoop loop;
+ bool error = false;
+ KWallet::errorCallback = [&]() {
+ if (loop.isRunning()) {
+ loop.exit(1);
+ } else {
+ error = true;
+ }
+ };
+
+
+ bool hasFolderCalled = false;
+ bool setFolderCalled = false;
+ QString password;
+ EwsSettings settings(0);
+ connect(&settings, &EwsSettings::passwordRequestFinished, this, [&](const QString &p) {
+ password = p;
+ loop.exit(0);
+ });
+ QTimer::singleShot(100, [&]() {
+ settings.requestPassword(false);
+ if (!wallet) {
+ qDebug() << "Wallet is null";
+ loop.exit(1);
+ return;
+ }
+ wallet->hasFolderCallback = [&hasFolderCalled](const QString &) {
+ hasFolderCalled = true;
+ return true;
+ };
+ wallet->createFolderCallback = [](const QString &) {
+ return false;
+ };
+ wallet->setFolderCallback = [&setFolderCalled](const QString &) {
+ setFolderCalled = true;
+ return true;
+ };
+ wallet->readPasswordCallback = [](const QString &, QString &password) {
+ password = QStringLiteral("foo");
+ return true;
+ };
+ wallet->doOpen(true);
+ });
+ QTimer timeoutTimer;
+ connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
+ qDebug() << "Test timeout";
+ loop.exit(1);
+ });
+ timeoutTimer.setSingleShot(true);
+ timeoutTimer.start(2000);
+
+ QVERIFY(error != true);
+
+ QVERIFY(loop.exec() == 0);
+
+ QVERIFY(password == QStringLiteral("foo"));
+ QVERIFY(hasFolderCalled);
+ QVERIFY(setFolderCalled);
+}
+
+void UtEwsSettings::writeNullPassword()
+{
+ KWallet::MyWallet *wallet = nullptr;
+ KWallet::openWalletCallback = [&wallet](KWallet::MyWallet *w) {
+ wallet = w;
+ return w;
+ };
+
+ QEventLoop loop;
+ bool error = false;
+ KWallet::errorCallback = [&]() {
+ if (loop.isRunning()) {
+ loop.exit(1);
+ } else {
+ error = true;
+ }
+ };
+
+ EwsSettings settings(0);
+ QTimer::singleShot(100, [&]() {
+ settings.setPassword(QString());
+ if (wallet) {
+ qDebug() << "Wallet is not null";
+ loop.exit(1);
+ return;
+ }
+ loop.exit(0);
+ });
+ QTimer timeoutTimer;
+ connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
+ qDebug() << "Test timeout";
+ loop.exit(1);
+ });
+ timeoutTimer.setSingleShot(true);
+ timeoutTimer.start(2000);
+
+ QVERIFY(error != true);
+
+ QVERIFY(loop.exec() == 0);
+}
+
+void UtEwsSettings::writeNullWallet()
+{
+ KWallet::MyWallet *wallet = nullptr;
+ KWallet::openWalletCallback = [&wallet](KWallet::MyWallet *) {
+ return nullptr;
+ };
+
+ QEventLoop loop;
+ bool error = false;
+ KWallet::errorCallback = [&]() {
+ if (loop.isRunning()) {
+ loop.exit(1);
+ } else {
+ error = true;
+ }
+ };
+
+ EwsSettings settings(0);
+ QTimer::singleShot(100, [&]() {
+ settings.setPassword(QStringLiteral("foo"));
+ if (wallet) {
+ qDebug() << "Wallet is not null";
+ loop.exit(1);
+ return;
+ }
+ loop.exit(0);
+ });
+ QTimer timeoutTimer;
+ connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
+ qDebug() << "Test timeout";
+ loop.exit(1);
+ });
+ timeoutTimer.setSingleShot(true);
+ timeoutTimer.start(2000);
+
+ QVERIFY(error != true);
+
+ QVERIFY(loop.exec() == 0);
+}
+
+void UtEwsSettings::writeTimeout()
+{
+ KWallet::MyWallet *wallet = nullptr;
+ KWallet::openWalletCallback = [&wallet](KWallet::MyWallet *w) {
+ wallet = w;
+ return w;
+ };
+
+ QEventLoop loop;
+ bool error = false;
+ KWallet::errorCallback = [&]() {
+ if (loop.isRunning()) {
+ loop.exit(1);
+ } else {
+ error = true;
+ }
+ };
+
+
+ bool hasFolderCalled = false;
+ bool createFolderCalled = false;
+ bool setFolderCalled = false;
+ QString password;
+ EwsSettings settings(0);
+ QTimer::singleShot(100, [&]() {
+ settings.setPassword(QStringLiteral("foo"));
+ if (!wallet) {
+ qDebug() << "Wallet is null";
+ loop.exit(1);
+ return;
+ }
+ wallet->hasFolderCallback = [&hasFolderCalled](const QString &) {
+ hasFolderCalled = true;
+ return false;
+ };
+ wallet->createFolderCallback = [&createFolderCalled](const QString &) {
+ createFolderCalled = true;
+ return true;
+ };
+ wallet->setFolderCallback = [&setFolderCalled](const QString &) {
+ setFolderCalled = true;
+ return false;
+ };
+ wallet->writePasswordCallback = [&](const QString &, const QString &p) {
+ password = p;
+ loop.exit(0);
+ return true;
+ };
+ });
+ QTimer timeoutTimer;
+ connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
+ qDebug() << "Test timeout";
+ loop.exit(2);
+ });
+ timeoutTimer.setSingleShot(true);
+ timeoutTimer.start(5000);
+
+ QVERIFY(error != true);
+
+ QVERIFY(loop.exec() == 2);
+
+ QVERIFY(password.isNull());
+ QVERIFY(!hasFolderCalled);
+ QVERIFY(!setFolderCalled);
+ QVERIFY(!createFolderCalled);
+}
+
+void UtEwsSettings::writeValidPassword()
+{
+ KWallet::MyWallet *wallet = nullptr;
+ KWallet::openWalletCallback = [&wallet](KWallet::MyWallet *w) {
+ wallet = w;
+ return w;
+ };
+
+ QEventLoop loop;
+ bool error = false;
+ KWallet::errorCallback = [&]() {
+ if (loop.isRunning()) {
+ loop.exit(1);
+ } else {
+ error = true;
+ }
+ };
+
+
+ bool hasFolderCalled = false;
+ bool createFolderCalled = false;
+ bool setFolderCalled = false;
+ QString password;
+ EwsSettings settings(0);
+ QTimer::singleShot(100, [&]() {
+ settings.setPassword(QStringLiteral("foo"));
+ if (!wallet) {
+ qDebug() << "Wallet is null";
+ loop.exit(1);
+ return;
+ }
+ wallet->hasFolderCallback = [&hasFolderCalled](const QString &) {
+ hasFolderCalled = true;
+ return false;
+ };
+ wallet->createFolderCallback = [&createFolderCalled](const QString &) {
+ createFolderCalled = true;
+ return true;
+ };
+ wallet->setFolderCallback = [&setFolderCalled](const QString &) {
+ setFolderCalled = true;
+ return false;
+ };
+ wallet->writePasswordCallback = [&](const QString &, const QString &p) {
+ password = p;
+ loop.exit(0);
+ return true;
+ };
+ wallet->doOpen(true);
+ });
+ QTimer timeoutTimer;
+ connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
+ qDebug() << "Test timeout";
+ loop.exit(1);
+ });
+ timeoutTimer.setSingleShot(true);
+ timeoutTimer.start(2000);
+
+ QVERIFY(error != true);
+
+ QVERIFY(loop.exec() == 0);
+
+ QVERIFY(password == QStringLiteral("foo"));
+ QVERIFY(hasFolderCalled);
+ QVERIFY(setFolderCalled);
+ QVERIFY(createFolderCalled);
+}
+
+QTEST_MAIN(UtEwsSettings)
+
+#include "ewssettings_ut.moc"