Page MenuHome GnuPG

No OneTemporary

diff --git a/autotests/newkeyapprovaldialogtest.cpp b/autotests/newkeyapprovaldialogtest.cpp
index 327c9016..ff6c96f1 100644
--- a/autotests/newkeyapprovaldialogtest.cpp
+++ b/autotests/newkeyapprovaldialogtest.cpp
@@ -1,1150 +1,1147 @@
/*
This file is part of libkleopatra's test suite.
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "testhelpers.h"
#include <Libkleo/Compliance>
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <Libkleo/KeySelectionCombo>
#include <Libkleo/NewKeyApprovalDialog>
#include <Libkleo/Predicates>
#include <Libkleo/Test>
#include <QCheckBox>
#include <QGroupBox>
#include <QLabel>
#include <QObject>
#include <QPushButton>
#include <QRadioButton>
#include <QSignalSpy>
#include <QTest>
#include <gpgme++/key.h>
#include <gpgme.h>
#include <memory>
#include <set>
using namespace Kleo;
using namespace Qt::StringLiterals;
namespace QTest
{
template<>
inline char *toString(const bool &t)
{
return t ? qstrdup("true") : qstrdup("false");
}
template<>
inline bool qCompare(bool const &t1, bool const &t2, const char *actual, const char *expected, const char *file, int line)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
auto formatter = Internal::genericToString<bool>;
return compare_helper(t1 == t2, "Compared values are not the same", &t1, &t2, formatter, formatter, actual, expected, file, line);
#else
auto actualVal = [&t1] {
return toString(t1);
};
auto expectedVal = [&t2] {
return toString(t2);
};
return compare_helper(t1 == t2, "Compared values are not the same", actualVal, expectedVal, actual, expected, file, line);
#endif
}
template<>
inline char *toString(const GpgME::Protocol &t)
{
return qstrdup(Formatting::displayName(t).toLocal8Bit().constData());
}
template<>
inline bool qCompare(GpgME::Protocol const &t1, GpgME::Protocol const &t2, const char *actual, const char *expected, const char *file, int line)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
auto formatter = Internal::genericToString<GpgME::Protocol>;
return compare_helper(t1 == t2, "Compared values are not the same", &t1, &t2, formatter, formatter, actual, expected, file, line);
#else
auto actualVal = [&t1] {
return toString(t1);
};
auto expectedVal = [&t2] {
return toString(t2);
};
return compare_helper(t1 == t2, "Compared values are not the same", actualVal, expectedVal, actual, expected, file, line);
#endif
}
}
namespace
{
// copied from NewKeyApprovalDialog::Private
enum Action {
Unset,
GenerateKey,
IgnoreKey,
};
auto mapValidity(GpgME::UserID::Validity validity)
{
switch (validity) {
default:
case GpgME::UserID::Unknown:
return GPGME_VALIDITY_UNKNOWN;
case GpgME::UserID::Undefined:
return GPGME_VALIDITY_UNDEFINED;
case GpgME::UserID::Never:
return GPGME_VALIDITY_NEVER;
case GpgME::UserID::Marginal:
return GPGME_VALIDITY_MARGINAL;
case GpgME::UserID::Full:
return GPGME_VALIDITY_FULL;
case GpgME::UserID::Ultimate:
return GPGME_VALIDITY_ULTIMATE;
}
}
// copied from gpgme; slightly modified
void _gpgme_key_add_subkey(gpgme_key_t key, gpgme_subkey_t *r_subkey)
{
gpgme_subkey_t subkey;
subkey = static_cast<gpgme_subkey_t>(calloc(1, sizeof *subkey));
Q_ASSERT(subkey);
subkey->keyid = subkey->_keyid;
subkey->_keyid[16] = '\0';
if (!key->subkeys) {
key->subkeys = subkey;
}
if (key->_last_subkey) {
key->_last_subkey->next = subkey;
}
key->_last_subkey = subkey;
*r_subkey = subkey;
}
GpgME::Key createTestKey(const char *uid,
GpgME::Protocol protocol = GpgME::UnknownProtocol,
KeyCache::KeyUsage usage = KeyCache::KeyUsage::AnyUsage,
GpgME::UserID::Validity validity = GpgME::UserID::Full)
{
static int count = 0;
count++;
gpgme_key_t key;
gpgme_key_from_uid(&key, uid);
Q_ASSERT(key);
Q_ASSERT(key->uids);
if (protocol != GpgME::UnknownProtocol) {
key->protocol = protocol == GpgME::OpenPGP ? GPGME_PROTOCOL_OpenPGP : GPGME_PROTOCOL_CMS;
}
const QByteArray fingerprint = QByteArray::number(count, 16).rightJustified(40, '0');
key->fpr = strdup(fingerprint.constData());
key->revoked = 0;
key->expired = 0;
key->disabled = 0;
key->can_encrypt = int(usage == KeyCache::KeyUsage::AnyUsage || usage == KeyCache::KeyUsage::Encrypt);
key->can_sign = int(usage == KeyCache::KeyUsage::AnyUsage || usage == KeyCache::KeyUsage::Sign);
key->has_encrypt = int(usage == KeyCache::KeyUsage::AnyUsage || usage == KeyCache::KeyUsage::Encrypt);
key->has_sign = int(usage == KeyCache::KeyUsage::AnyUsage || usage == KeyCache::KeyUsage::Sign);
key->secret = 1;
key->uids->validity = mapValidity(validity);
key->keylist_mode = GPGME_KEYLIST_MODE_VALIDATE;
// add a usable VS-NfD-compliant subkey
gpgme_subkey_t subkey;
_gpgme_key_add_subkey(key, &subkey);
subkey->is_de_vs = 1;
subkey->can_encrypt = key->can_encrypt;
subkey->can_sign = key->can_sign;
return GpgME::Key(key, false);
}
auto testKey(const char *address, GpgME::Protocol protocol = GpgME::UnknownProtocol)
{
const auto email = GpgME::UserID::addrSpecFromString(address);
const auto keys = KeyCache::instance()->findByEMailAddress(email);
for (const auto &key : keys) {
if (protocol == GpgME::UnknownProtocol || key.protocol() == protocol) {
return key;
}
}
return GpgME::Key();
}
-void waitForKeySelectionCombosBeingInitialized(const QDialog *dialog)
-{
- QVERIFY(dialog);
- auto combo = dialog->findChild<KeySelectionCombo *>();
- QVERIFY(combo);
-
- const auto spy = std::make_unique<QSignalSpy>(combo, &KeySelectionCombo::keyListingFinished);
- QVERIFY(spy->isValid());
- QVERIFY(spy->wait(10));
-}
+#define waitForKeySelectionCombosBeingInitialized(dialog) \
+ do { \
+ QVERIFY(dialog); \
+ auto combo = dialog->findChild<KeySelectionCombo *>(); \
+ QVERIFY(combo); \
+ const auto spy = std::make_unique<QSignalSpy>(combo, &KeySelectionCombo::keyListingFinished); \
+ QVERIFY(spy->isValid()); \
+ QVERIFY(spy->wait(10)); \
+ } while (false)
template<typename T>
struct Widgets {
std::vector<T *> visible;
std::vector<T *> hidden;
};
template<typename T>
Widgets<T> visibleAndHiddenWidgets(const QList<T *> &widgets)
{
Widgets<T> result;
std::partition_copy(std::begin(widgets),
std::end(widgets),
std::back_inserter(result.visible),
std::back_inserter(result.hidden),
std::mem_fn(&QWidget::isVisible));
return result;
}
enum Visibility {
IsHidden,
IsVisible,
};
enum CheckedState {
IsUnchecked,
IsChecked,
};
-template<typename T>
-void verifyProtocolButton(const T *button, Visibility expectedVisibility, CheckedState expectedCheckedState)
-{
- QVERIFY(button);
- QCOMPARE(button->isVisible(), expectedVisibility == IsVisible);
- QCOMPARE(button->isChecked(), expectedCheckedState == IsChecked);
-}
-
-template<typename T>
-void verifyWidgetVisibility(const T *widget, Visibility expectedVisibility)
-{
- QVERIFY(widget);
- QCOMPARE(widget->isVisible(), expectedVisibility == IsVisible);
-}
-
-template<typename T>
-void verifyWidgetsVisibility(const QList<T> &widgets, Visibility expectedVisibility)
-{
- for (auto w : widgets) {
- verifyWidgetVisibility(w, expectedVisibility);
- }
-}
-
-void verifyProtocolLabels(const QList<QLabel *> &labels, int expectedNumber, Visibility expectedVisibility)
-{
- QCOMPARE(labels.size(), expectedNumber);
- verifyWidgetsVisibility(labels, expectedVisibility);
-}
-
-bool listsOfKeysAreEqual(const std::vector<GpgME::Key> &l1, const std::vector<GpgME::Key> &l2)
+#define verifyProtocolButton(button, expectedVisibility, expectedCheckedState) \
+ do { \
+ QVERIFY(button); \
+ QCOMPARE(button->isVisible(), expectedVisibility == IsVisible); \
+ QCOMPARE(button->isChecked(), expectedCheckedState == IsChecked); \
+ } while (false)
+
+#define verifyWidgetVisibility(widget, expectedVisibility) \
+ do { \
+ QVERIFY(widget); \
+ QCOMPARE(widget->isVisible(), expectedVisibility == IsVisible); \
+ } while (false)
+
+#define verifyWidgetsVisibility(widgets, expectedVisibility) \
+ do { \
+ for (auto w : widgets) { \
+ verifyWidgetVisibility(w, expectedVisibility); \
+ } \
+ } while (false)
+
+#define verifyProtocolLabels(labels, expectedNumber, expectedVisibility) \
+ do { \
+ QCOMPARE(labels.size(), expectedNumber); \
+ verifyWidgetsVisibility(labels, expectedVisibility); \
+ } while (false)
+
+static bool listsOfKeysAreEqual(const std::vector<GpgME::Key> &l1, const std::vector<GpgME::Key> &l2)
{
return std::equal(std::begin(l1), std::end(l1), std::begin(l2), std::end(l2), ByFingerprint<std::equal_to>());
}
-void verifySolution(const KeyResolver::Solution &actual, const KeyResolver::Solution &expected)
-{
- QCOMPARE(actual.protocol, expected.protocol);
-
- QVERIFY(listsOfKeysAreEqual(actual.signingKeys, expected.signingKeys));
-
- QVERIFY(std::equal(actual.encryptionKeys.constKeyValueBegin(),
- actual.encryptionKeys.constKeyValueEnd(),
- expected.encryptionKeys.constKeyValueBegin(),
- expected.encryptionKeys.constKeyValueEnd(),
- [](const auto &kv1, const auto &kv2) {
- return kv1.first == kv2.first && listsOfKeysAreEqual(kv1.second, kv2.second);
- }));
-}
+#define verifySolution(actual, expected) \
+ do { \
+ QCOMPARE(actual.protocol, expected.protocol); \
+ QVERIFY(listsOfKeysAreEqual(actual.signingKeys, expected.signingKeys)); \
+ QVERIFY(std::equal(actual.encryptionKeys.constKeyValueBegin(), \
+ actual.encryptionKeys.constKeyValueEnd(), \
+ expected.encryptionKeys.constKeyValueBegin(), \
+ expected.encryptionKeys.constKeyValueEnd(), \
+ [](const auto &kv1, const auto &kv2) { \
+ return kv1.first == kv2.first && listsOfKeysAreEqual(kv1.second, kv2.second); \
+ })); \
+ } while (false)
void switchKeySelectionCombosFromGenerateKeyToIgnoreKey(const QList<KeySelectionCombo *> &combos)
{
for (auto combo : combos) {
if (combo->currentData(Qt::UserRole).toInt() == GenerateKey) {
const auto ignoreIndex = combo->findData(IgnoreKey);
QVERIFY(ignoreIndex != -1);
combo->setCurrentIndex(ignoreIndex);
}
}
}
}
class NewKeyApprovalDialogTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase()
{
#ifdef Q_OS_WIN
QSKIP("UI tests don't run on Windows");
#endif
}
void init()
{
// hold a reference to the key cache to avoid rebuilding while the test is running
mKeyCache = KeyCache::instance();
KeyCache::mutableInstance()->setKeys({
createTestKey("sender@example.net", GpgME::OpenPGP, KeyCache::KeyCache::KeyUsage::AnyUsage),
createTestKey("sender@example.net", GpgME::CMS, KeyCache::KeyCache::KeyUsage::AnyUsage),
createTestKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP, KeyCache::KeyCache::KeyUsage::Encrypt),
createTestKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS, KeyCache::KeyCache::KeyUsage::Encrypt),
createTestKey("Marginal Validity <marginal-openpgp@example.net>", GpgME::OpenPGP, KeyCache::KeyCache::KeyUsage::Encrypt, GpgME::UserID::Marginal),
});
}
void cleanup()
{
// verify that nobody else holds a reference to the key cache
QCOMPARE(mKeyCache.use_count(), 1);
mKeyCache.reset();
}
void test__verify_test_keys()
{
QVERIFY(!testKey("sender@example.net", GpgME::OpenPGP).isNull());
QVERIFY(!testKey("sender@example.net", GpgME::CMS).isNull());
QVERIFY(!testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP).isNull());
QVERIFY(!testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS).isNull());
QVERIFY(!testKey("Marginal Validity <marginal-openpgp@example.net>", GpgME::OpenPGP).isNull());
}
void test__both_protocols_allowed__mixed_not_allowed__openpgp_preferred()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = false;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::OpenPGP,
{testKey("sender@example.net", GpgME::OpenPGP)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP)}},
},
};
const KeyResolver::Solution alternativeSolution = {
GpgME::CMS,
{testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::CMS)}},
},
};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
verifyProtocolButton(dialog->findChild<QRadioButton *>(QStringLiteral("openpgp button")), IsVisible, IsChecked);
verifyProtocolButton(dialog->findChild<QRadioButton *>(QStringLiteral("smime button")), IsVisible, IsUnchecked);
const auto signingKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key")));
QCOMPARE(signingKeyWidgets.visible.size(), 1);
QCOMPARE(signingKeyWidgets.hidden.size(), 1);
QCOMPARE(signingKeyWidgets.visible[0]->defaultKey(GpgME::OpenPGP), preferredSolution.signingKeys[0].primaryFingerprint());
QCOMPARE(signingKeyWidgets.hidden[0]->defaultKey(GpgME::CMS), alternativeSolution.signingKeys[0].primaryFingerprint());
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
QCOMPARE(encryptionKeyWidgets.visible.size(), 3);
QCOMPARE(encryptionKeyWidgets.hidden.size(), 3);
// encryption key widgets for sender come first (visible for OpenPGP, hidden for S/MIME)
QCOMPARE(encryptionKeyWidgets.visible[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.visible[0]->defaultKey(GpgME::OpenPGP), preferredSolution.encryptionKeys.value(sender)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.hidden[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.hidden[0]->defaultKey(GpgME::CMS), alternativeSolution.encryptionKeys.value(sender)[0].primaryFingerprint());
// encryption key widgets for other recipients follow (visible for OpenPGP, hidden for S/MIME)
QCOMPARE(encryptionKeyWidgets.visible[1]->property("address").toString(), "prefer-openpgp@example.net");
QCOMPARE(encryptionKeyWidgets.visible[1]->defaultKey(GpgME::OpenPGP),
preferredSolution.encryptionKeys.value(u"prefer-openpgp@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.hidden[1]->property("address").toString(), "prefer-openpgp@example.net");
QVERIFY(encryptionKeyWidgets.hidden[1]->defaultKey(GpgME::CMS).isEmpty());
QCOMPARE(encryptionKeyWidgets.visible[2]->property("address").toString(), "prefer-smime@example.net");
QVERIFY(encryptionKeyWidgets.visible[2]->defaultKey(GpgME::OpenPGP).isEmpty());
QCOMPARE(encryptionKeyWidgets.hidden[2]->property("address").toString(), "prefer-smime@example.net");
QCOMPARE(encryptionKeyWidgets.hidden[2]->defaultKey(GpgME::CMS),
alternativeSolution.encryptionKeys.value(u"prefer-smime@example.net"_s)[0].primaryFingerprint());
}
void test__both_protocols_allowed__mixed_not_allowed__smime_preferred()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = false;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::CMS,
{testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {
GpgME::OpenPGP,
{testKey("sender@example.net", GpgME::OpenPGP)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP)}},
},
};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
verifyProtocolButton(dialog->findChild<QRadioButton *>(QStringLiteral("openpgp button")), IsVisible, IsUnchecked);
verifyProtocolButton(dialog->findChild<QRadioButton *>(QStringLiteral("smime button")), IsVisible, IsChecked);
const auto signingKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key")));
QCOMPARE(signingKeyWidgets.visible.size(), 1);
QCOMPARE(signingKeyWidgets.hidden.size(), 1);
QCOMPARE(signingKeyWidgets.visible[0]->defaultKey(GpgME::CMS), preferredSolution.signingKeys[0].primaryFingerprint());
QCOMPARE(signingKeyWidgets.hidden[0]->defaultKey(GpgME::OpenPGP), alternativeSolution.signingKeys[0].primaryFingerprint());
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
QCOMPARE(encryptionKeyWidgets.visible.size(), 3);
QCOMPARE(encryptionKeyWidgets.hidden.size(), 3);
// encryption key widgets for sender come first (visible for S/MIME, hidden for OpenPGP)
QCOMPARE(encryptionKeyWidgets.visible[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.visible[0]->defaultKey(GpgME::CMS), preferredSolution.encryptionKeys.value(sender)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.hidden[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.hidden[0]->defaultKey(GpgME::OpenPGP), alternativeSolution.encryptionKeys.value(sender)[0].primaryFingerprint());
// encryption key widgets for other recipients follow (visible for OpenPGP, hidden for S/MIME)
QCOMPARE(encryptionKeyWidgets.visible[1]->property("address").toString(), "prefer-openpgp@example.net");
QVERIFY(encryptionKeyWidgets.visible[1]->defaultKey(GpgME::CMS).isEmpty());
QCOMPARE(encryptionKeyWidgets.hidden[1]->property("address").toString(), "prefer-openpgp@example.net");
QCOMPARE(encryptionKeyWidgets.hidden[1]->defaultKey(GpgME::OpenPGP),
alternativeSolution.encryptionKeys.value(u"prefer-openpgp@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.visible[2]->property("address").toString(), "prefer-smime@example.net");
QCOMPARE(encryptionKeyWidgets.visible[2]->defaultKey(GpgME::CMS),
preferredSolution.encryptionKeys.value(u"prefer-smime@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.hidden[2]->property("address").toString(), "prefer-smime@example.net");
QVERIFY(encryptionKeyWidgets.hidden[2]->defaultKey(GpgME::OpenPGP).isEmpty());
}
void test__openpgp_only()
{
const GpgME::Protocol forcedProtocol = GpgME::OpenPGP;
const bool allowMixed = false;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::OpenPGP,
{testKey("sender@example.net", GpgME::OpenPGP)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
verifyProtocolButton(dialog->findChild<QRadioButton *>(QStringLiteral("openpgp button")), IsHidden, IsChecked);
verifyProtocolButton(dialog->findChild<QRadioButton *>(QStringLiteral("smime button")), IsHidden, IsUnchecked);
const auto signingKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key")));
QCOMPARE(signingKeyWidgets.visible.size(), 1);
QCOMPARE(signingKeyWidgets.hidden.size(), 0);
QCOMPARE(signingKeyWidgets.visible[0]->defaultKey(GpgME::OpenPGP), preferredSolution.signingKeys[0].primaryFingerprint());
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
QCOMPARE(encryptionKeyWidgets.visible.size(), 3);
QCOMPARE(encryptionKeyWidgets.hidden.size(), 0);
// encryption key widget for sender comes first
QCOMPARE(encryptionKeyWidgets.visible[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.visible[0]->defaultKey(GpgME::OpenPGP), preferredSolution.encryptionKeys.value(sender)[0].primaryFingerprint());
// encryption key widgets for other recipients follow
QCOMPARE(encryptionKeyWidgets.visible[1]->property("address").toString(), "prefer-openpgp@example.net");
QCOMPARE(encryptionKeyWidgets.visible[1]->defaultKey(GpgME::OpenPGP),
preferredSolution.encryptionKeys.value(u"prefer-openpgp@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.visible[2]->property("address").toString(), "prefer-smime@example.net");
QVERIFY(encryptionKeyWidgets.visible[2]->defaultKey(GpgME::OpenPGP).isEmpty());
}
void test__smime_only()
{
const GpgME::Protocol forcedProtocol = GpgME::CMS;
const bool allowMixed = false;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::CMS,
{testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
verifyProtocolButton(dialog->findChild<QRadioButton *>(QStringLiteral("openpgp button")), IsHidden, IsUnchecked);
verifyProtocolButton(dialog->findChild<QRadioButton *>(QStringLiteral("smime button")), IsHidden, IsChecked);
const auto signingKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key")));
QCOMPARE(signingKeyWidgets.visible.size(), 1);
QCOMPARE(signingKeyWidgets.hidden.size(), 0);
QCOMPARE(signingKeyWidgets.visible[0]->defaultKey(GpgME::CMS), preferredSolution.signingKeys[0].primaryFingerprint());
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
QCOMPARE(encryptionKeyWidgets.visible.size(), 3);
QCOMPARE(encryptionKeyWidgets.hidden.size(), 0);
// encryption key widget for sender comes first
QCOMPARE(encryptionKeyWidgets.visible[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.visible[0]->defaultKey(GpgME::CMS), preferredSolution.encryptionKeys.value(sender)[0].primaryFingerprint());
// encryption key widgets for other recipients follow
QCOMPARE(encryptionKeyWidgets.visible[1]->property("address").toString(), "prefer-openpgp@example.net");
QVERIFY(encryptionKeyWidgets.visible[1]->defaultKey(GpgME::CMS).isEmpty());
QCOMPARE(encryptionKeyWidgets.visible[2]->property("address").toString(), "prefer-smime@example.net");
QCOMPARE(encryptionKeyWidgets.visible[2]->defaultKey(GpgME::CMS),
preferredSolution.encryptionKeys.value(u"prefer-smime@example.net"_s)[0].primaryFingerprint());
}
void test__both_protocols_allowed__mixed_allowed()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("unknown@example.net"), {}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
verifyProtocolButton(dialog->findChild<QCheckBox *>(QStringLiteral("openpgp button")), IsVisible, IsChecked);
verifyProtocolButton(dialog->findChild<QCheckBox *>(QStringLiteral("smime button")), IsVisible, IsChecked);
verifyProtocolLabels(dialog->findChildren<QLabel *>(QStringLiteral("protocol label")), 4, IsVisible);
const auto signingKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key")));
QCOMPARE(signingKeyWidgets.visible.size(), 2);
QCOMPARE(signingKeyWidgets.hidden.size(), 0);
QCOMPARE(signingKeyWidgets.visible[0]->defaultKey(GpgME::OpenPGP), preferredSolution.signingKeys[0].primaryFingerprint());
QCOMPARE(signingKeyWidgets.visible[1]->defaultKey(GpgME::CMS), preferredSolution.signingKeys[1].primaryFingerprint());
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
QCOMPARE(encryptionKeyWidgets.visible.size(), 5);
QCOMPARE(encryptionKeyWidgets.hidden.size(), 0);
// encryption key widgets for sender come first
QCOMPARE(encryptionKeyWidgets.visible[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.visible[0]->defaultKey(GpgME::OpenPGP), preferredSolution.encryptionKeys.value(sender)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.visible[1]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.visible[1]->defaultKey(GpgME::CMS), preferredSolution.encryptionKeys.value(sender)[1].primaryFingerprint());
// encryption key widgets for other recipients follow
QCOMPARE(encryptionKeyWidgets.visible[2]->property("address").toString(), "prefer-openpgp@example.net");
QCOMPARE(encryptionKeyWidgets.visible[2]->defaultKey(GpgME::UnknownProtocol),
preferredSolution.encryptionKeys.value(u"prefer-openpgp@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.visible[3]->property("address").toString(), "prefer-smime@example.net");
QCOMPARE(encryptionKeyWidgets.visible[3]->defaultKey(GpgME::UnknownProtocol),
preferredSolution.encryptionKeys.value(u"prefer-smime@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.visible[4]->property("address").toString(), "unknown@example.net");
QVERIFY(encryptionKeyWidgets.visible[4]->defaultKey(GpgME::UnknownProtocol).isEmpty());
}
void test__both_protocols_allowed__mixed_allowed__openpgp_only_preferred_solution()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::OpenPGP,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("unknown@example.net"), {}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
verifyProtocolButton(dialog->findChild<QCheckBox *>(QStringLiteral("openpgp button")), IsVisible, IsChecked);
verifyProtocolButton(dialog->findChild<QCheckBox *>(QStringLiteral("smime button")), IsVisible, IsUnchecked);
verifyProtocolLabels(dialog->findChildren<QLabel *>(QStringLiteral("protocol label")), 4, IsHidden);
const auto signingKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key")));
QCOMPARE(signingKeyWidgets.visible.size(), 1);
QCOMPARE(signingKeyWidgets.hidden.size(), 1);
QCOMPARE(signingKeyWidgets.visible[0]->defaultKey(GpgME::OpenPGP), preferredSolution.signingKeys[0].primaryFingerprint());
QCOMPARE(signingKeyWidgets.hidden[0]->defaultKey(GpgME::CMS), preferredSolution.signingKeys[1].primaryFingerprint());
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
QCOMPARE(encryptionKeyWidgets.visible.size(), 3);
QCOMPARE(encryptionKeyWidgets.hidden.size(), 1);
// encryption key widgets for sender come first
QCOMPARE(encryptionKeyWidgets.visible[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.visible[0]->defaultKey(GpgME::OpenPGP), preferredSolution.encryptionKeys.value(sender)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.hidden[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.hidden[0]->defaultKey(GpgME::CMS), preferredSolution.encryptionKeys.value(sender)[1].primaryFingerprint());
// encryption key widgets for other recipients follow
QCOMPARE(encryptionKeyWidgets.visible[1]->property("address").toString(), "prefer-openpgp@example.net");
QCOMPARE(encryptionKeyWidgets.visible[1]->defaultKey(GpgME::UnknownProtocol),
preferredSolution.encryptionKeys.value(u"prefer-openpgp@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.visible[2]->property("address").toString(), "unknown@example.net");
QVERIFY(encryptionKeyWidgets.visible[2]->defaultKey(GpgME::UnknownProtocol).isEmpty());
}
void test__both_protocols_allowed__mixed_allowed__smime_only_preferred_solution()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::CMS,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("unknown@example.net"), {}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
verifyProtocolButton(dialog->findChild<QCheckBox *>(QStringLiteral("openpgp button")), IsVisible, IsUnchecked);
verifyProtocolButton(dialog->findChild<QCheckBox *>(QStringLiteral("smime button")), IsVisible, IsChecked);
verifyProtocolLabels(dialog->findChildren<QLabel *>(QStringLiteral("protocol label")), 4, IsHidden);
const auto signingKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key")));
QCOMPARE(signingKeyWidgets.visible.size(), 1);
QCOMPARE(signingKeyWidgets.hidden.size(), 1);
QCOMPARE(signingKeyWidgets.visible[0]->defaultKey(GpgME::CMS), preferredSolution.signingKeys[1].primaryFingerprint());
QCOMPARE(signingKeyWidgets.hidden[0]->defaultKey(GpgME::OpenPGP), preferredSolution.signingKeys[0].primaryFingerprint());
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
QCOMPARE(encryptionKeyWidgets.visible.size(), 3);
QCOMPARE(encryptionKeyWidgets.hidden.size(), 1);
// encryption key widgets for sender come first
QCOMPARE(encryptionKeyWidgets.visible[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.visible[0]->defaultKey(GpgME::CMS), preferredSolution.encryptionKeys.value(sender)[1].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.hidden[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.hidden[0]->defaultKey(GpgME::OpenPGP), preferredSolution.encryptionKeys.value(sender)[0].primaryFingerprint());
// encryption key widgets for other recipients follow
QCOMPARE(encryptionKeyWidgets.visible[1]->property("address").toString(), "prefer-smime@example.net");
QCOMPARE(encryptionKeyWidgets.visible[1]->defaultKey(GpgME::UnknownProtocol),
preferredSolution.encryptionKeys.value(u"prefer-smime@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.visible[2]->property("address").toString(), "unknown@example.net");
QVERIFY(encryptionKeyWidgets.visible[2]->defaultKey(GpgME::UnknownProtocol).isEmpty());
}
void test__both_protocols_allowed__mixed_allowed__no_sender_keys()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("unknown@example.net"), {}},
{QStringLiteral("sender@example.net"), {}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
const auto signingKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key")));
QCOMPARE(signingKeyWidgets.visible.size(), 2);
QCOMPARE(signingKeyWidgets.hidden.size(), 0);
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
QCOMPARE(encryptionKeyWidgets.visible.size(), 5);
QCOMPARE(encryptionKeyWidgets.hidden.size(), 0);
// encryption key widgets for sender come first
QCOMPARE(encryptionKeyWidgets.visible[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets.visible[1]->property("address").toString(), sender);
// encryption key widgets for other recipients follow
QCOMPARE(encryptionKeyWidgets.visible[2]->property("address").toString(), "prefer-openpgp@example.net");
QCOMPARE(encryptionKeyWidgets.visible[2]->defaultKey(GpgME::UnknownProtocol),
preferredSolution.encryptionKeys.value(u"prefer-openpgp@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.visible[3]->property("address").toString(), "prefer-smime@example.net");
QCOMPARE(encryptionKeyWidgets.visible[3]->defaultKey(GpgME::UnknownProtocol),
preferredSolution.encryptionKeys.value(u"prefer-smime@example.net"_s)[0].primaryFingerprint());
QCOMPARE(encryptionKeyWidgets.visible[4]->property("address").toString(), "unknown@example.net");
QVERIFY(encryptionKeyWidgets.visible[4]->defaultKey(GpgME::UnknownProtocol).isEmpty());
}
void test__both_protocols_allowed__mixed_allowed__encrypt_only()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("unknown@example.net"), {}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, false, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
const auto signingKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key")));
QCOMPARE(signingKeyWidgets.visible.size(), 0);
QCOMPARE(signingKeyWidgets.hidden.size(), 0);
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
QCOMPARE(encryptionKeyWidgets.visible.size(), 5);
QCOMPARE(encryptionKeyWidgets.hidden.size(), 0);
}
void test__ok_button_shows_generate_if_generate_is_selected()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::OpenPGP,
{}, // no signing keys to get "Generate key" choice in OpenPGP combo
{{QStringLiteral("sender@example.net"), {}}} // no encryption keys to get "Generate key" choice in OpenPGP combo
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
const auto okButton = dialog->findChild<QPushButton *>("ok button");
QVERIFY(okButton);
QVERIFY(okButton->text() != u"Generate"_s);
{
// get the first signing key combo which is the OpenPGP one
const auto signingKeyCombo = dialog->findChild<KeySelectionCombo *>("signing key");
verifyWidgetVisibility(signingKeyCombo, IsVisible);
const auto originalIndex = signingKeyCombo->currentIndex();
const auto generateIndex = signingKeyCombo->findData(GenerateKey);
QVERIFY(generateIndex != -1);
signingKeyCombo->setCurrentIndex(generateIndex);
QCOMPARE(okButton->text(), "Generate");
signingKeyCombo->setCurrentIndex(originalIndex);
QVERIFY(okButton->text() != u"Generate"_s);
}
{
// get the first encryption key combo which is the OpenPGP one for the sender
const auto encryptionKeyCombo = dialog->findChild<KeySelectionCombo *>("encryption key");
verifyWidgetVisibility(encryptionKeyCombo, IsVisible);
const auto originalIndex = encryptionKeyCombo->currentIndex();
const auto generateIndex = encryptionKeyCombo->findData(GenerateKey);
QVERIFY(generateIndex != -1);
encryptionKeyCombo->setCurrentIndex(generateIndex);
QCOMPARE(okButton->text(), QStringLiteral("Generate"));
encryptionKeyCombo->setCurrentIndex(originalIndex);
QVERIFY(okButton->text() != QStringLiteral("Generate"));
}
}
void test__ok_button_does_not_show_generate_if_generate_is_selected_in_hidden_combos()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::CMS, // enables S/MIME as default protocol, hides OpenPGP combos
{}, // no signing keys to get "Generate key" choice in OpenPGP combo
{{QStringLiteral("sender@example.net"), {}}} // no encryption keys to get "Generate key" choice in OpenPGP combo
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
const auto okButton = dialog->findChild<QPushButton *>("ok button");
QVERIFY(okButton);
QVERIFY(okButton->text() != u"Generate"_s);
{
// get the first signing key combo which is the OpenPGP one
const auto signingKeyCombo = dialog->findChild<KeySelectionCombo *>("signing key");
verifyWidgetVisibility(signingKeyCombo, IsHidden);
const auto originalIndex = signingKeyCombo->currentIndex();
const auto generateIndex = signingKeyCombo->findData(GenerateKey);
QVERIFY(generateIndex != -1);
signingKeyCombo->setCurrentIndex(generateIndex);
QVERIFY(okButton->text() != QStringLiteral("Generate"));
signingKeyCombo->setCurrentIndex(originalIndex);
QVERIFY(okButton->text() != QStringLiteral("Generate"));
}
{
// get the first encryption key combo which is the OpenPGP one for the sender
const auto encryptionKeyCombo = dialog->findChild<KeySelectionCombo *>("encryption key");
verifyWidgetVisibility(encryptionKeyCombo, IsHidden);
const auto originalIndex = encryptionKeyCombo->currentIndex();
const auto generateIndex = encryptionKeyCombo->findData(GenerateKey);
QVERIFY(generateIndex != -1);
encryptionKeyCombo->setCurrentIndex(generateIndex);
QVERIFY(okButton->text() != QStringLiteral("Generate"));
encryptionKeyCombo->setCurrentIndex(originalIndex);
QVERIFY(okButton->text() != QStringLiteral("Generate"));
}
}
void test__ok_button_is_disabled_if_ignore_is_selected_in_all_visible_encryption_combos()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::OpenPGP,
{}, // no signing keys to get "Generate key" choice in OpenPGP combo
{{QStringLiteral("sender@example.net"), {}}} // no encryption keys to get "Generate key" choice in OpenPGP combo
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
const auto okButton = dialog->findChild<QPushButton *>(QStringLiteral("ok button"));
QVERIFY(okButton);
QVERIFY(okButton->isEnabled());
const auto encryptionKeyWidgets = visibleAndHiddenWidgets(dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key")));
for (auto combo : encryptionKeyWidgets.visible) {
const auto ignoreIndex = combo->findData(IgnoreKey);
QVERIFY(ignoreIndex != -1);
combo->setCurrentIndex(ignoreIndex);
}
QVERIFY(!okButton->isEnabled());
}
void test__vs_de_compliance__all_keys_fully_valid()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
Tests::FakeCryptoConfigStringValue fakeCompliance{"gpg", "compliance", QStringLiteral("de-vs")};
Tests::FakeCryptoConfigIntValue fakeDeVsCompliance{"gpg", "compliance_de_vs", 1};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
const auto complianceLabel = dialog->findChild<QLabel *>(QStringLiteral("compliance label"));
verifyWidgetVisibility(complianceLabel, IsVisible);
QVERIFY(!complianceLabel->text().contains(DeVSCompliance::name(false)));
}
void test__vs_de_compliance__not_all_keys_fully_valid()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("marginal-openpgp@example.net"), {testKey("Marginal Validity <marginal-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
Tests::FakeCryptoConfigStringValue fakeCompliance{"gpg", "compliance", QStringLiteral("de-vs")};
Tests::FakeCryptoConfigIntValue fakeDeVsCompliance{"gpg", "compliance_de_vs", 1};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
const auto complianceLabel = dialog->findChild<QLabel *>(QStringLiteral("compliance label"));
verifyWidgetVisibility(complianceLabel, IsVisible);
QVERIFY(complianceLabel->text().contains(DeVSCompliance::name(false)));
}
void test__vs_de_compliance__null_keys_are_ignored()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("unknown@example.net"), {}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
Tests::FakeCryptoConfigStringValue fakeCompliance{"gpg", "compliance", QStringLiteral("de-vs")};
Tests::FakeCryptoConfigIntValue fakeDeVsCompliance{"gpg", "compliance_de_vs", 1};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
const auto complianceLabel = dialog->findChild<QLabel *>(QStringLiteral("compliance label"));
verifyWidgetVisibility(complianceLabel, IsVisible);
QVERIFY(!complianceLabel->text().contains(DeVSCompliance::name(false)));
}
void test__sign_and_encrypt_to_self_only()
{
const GpgME::Protocol forcedProtocol = GpgME::OpenPGP;
const bool allowMixed = false;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::OpenPGP,
{testKey("sender@example.net", GpgME::OpenPGP)},
{
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
QVERIFY(!dialog->findChild<QGroupBox *>(QStringLiteral("encrypt-to-others box")));
}
void test__sign_and_encrypt_to_self_and_others()
{
const GpgME::Protocol forcedProtocol = GpgME::OpenPGP;
const bool allowMixed = false;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::OpenPGP,
{testKey("sender@example.net", GpgME::OpenPGP)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
QVERIFY(dialog->findChild<QGroupBox *>(QStringLiteral("encrypt-to-others box")));
}
void test__result_does_not_include_null_keys()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("unknown@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("unknown@example.net"), {}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
switchKeySelectionCombosFromGenerateKeyToIgnoreKey(dialog->findChildren<KeySelectionCombo *>());
const QSignalSpy dialogAcceptedSpy{dialog.get(), &QDialog::accepted};
QVERIFY(dialogAcceptedSpy.isValid());
const auto okButton = dialog->findChild<QPushButton *>(QStringLiteral("ok button"));
QVERIFY(okButton);
QVERIFY(okButton->isEnabled());
okButton->click();
QCOMPARE(dialogAcceptedSpy.count(), 1);
- verifySolution(dialog->result(),
- {GpgME::UnknownProtocol,
- {},
- {
- {QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
- {QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
- }});
+ const KeyResolver::Solution expectedSolution = {
+ GpgME::UnknownProtocol,
+ {},
+ {
+ {QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
+ {QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
+ }};
+ verifySolution(dialog->result(), expectedSolution);
}
void test__result_has_keys_for_both_protocols_if_both_are_needed()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
switchKeySelectionCombosFromGenerateKeyToIgnoreKey(dialog->findChildren<KeySelectionCombo *>());
const QSignalSpy dialogAcceptedSpy{dialog.get(), &QDialog::accepted};
QVERIFY(dialogAcceptedSpy.isValid());
const auto okButton = dialog->findChild<QPushButton *>(QStringLiteral("ok button"));
QVERIFY(okButton);
QVERIFY(okButton->isEnabled());
okButton->click();
QCOMPARE(dialogAcceptedSpy.count(), 1);
verifySolution(dialog->result(), preferredSolution);
}
void test__result_has_only_openpgp_keys_if_openpgp_protocol_selected()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
switchKeySelectionCombosFromGenerateKeyToIgnoreKey(dialog->findChildren<KeySelectionCombo *>());
const auto smimeButton = dialog->findChild<QCheckBox *>(QStringLiteral("smime button"));
QVERIFY(smimeButton);
smimeButton->click();
QVERIFY(!smimeButton->isChecked());
const QSignalSpy dialogAcceptedSpy{dialog.get(), &QDialog::accepted};
QVERIFY(dialogAcceptedSpy.isValid());
const auto okButton = dialog->findChild<QPushButton *>(QStringLiteral("ok button"));
QVERIFY(okButton);
QVERIFY(okButton->isEnabled());
okButton->click();
QCOMPARE(dialogAcceptedSpy.count(), 1);
- verifySolution(dialog->result(),
- {GpgME::OpenPGP,
- {testKey("sender@example.net", GpgME::OpenPGP)},
- {
- {QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
- {QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP)}},
- }});
+ const KeyResolver::Solution expectedSolution = {
+ GpgME::OpenPGP,
+ {testKey("sender@example.net", GpgME::OpenPGP)},
+ {
+ {QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
+ {QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP)}},
+ }};
+ verifySolution(dialog->result(), expectedSolution);
}
void test__result_has_only_smime_keys_if_smime_protocol_selected()
{
const GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
const bool allowMixed = true;
const QString sender = QStringLiteral("sender@example.net");
const KeyResolver::Solution preferredSolution = {
GpgME::UnknownProtocol,
{testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)},
{
{QStringLiteral("prefer-openpgp@example.net"), {testKey("Full Trust <prefer-openpgp@example.net>", GpgME::OpenPGP)}},
{QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
{QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS)}},
},
};
const KeyResolver::Solution alternativeSolution = {};
const auto dialog = std::make_unique<NewKeyApprovalDialog>(true, true, sender, preferredSolution, alternativeSolution, allowMixed, forcedProtocol);
dialog->show();
waitForKeySelectionCombosBeingInitialized(dialog.get());
switchKeySelectionCombosFromGenerateKeyToIgnoreKey(dialog->findChildren<KeySelectionCombo *>());
const auto openPGPButton = dialog->findChild<QCheckBox *>(QStringLiteral("openpgp button"));
QVERIFY(openPGPButton);
openPGPButton->click();
QVERIFY(!openPGPButton->isChecked());
const QSignalSpy dialogAcceptedSpy{dialog.get(), &QDialog::accepted};
QVERIFY(dialogAcceptedSpy.isValid());
const auto okButton = dialog->findChild<QPushButton *>(QStringLiteral("ok button"));
QVERIFY(okButton);
QVERIFY(okButton->isEnabled());
okButton->click();
QCOMPARE(dialogAcceptedSpy.count(), 1);
- verifySolution(dialog->result(),
- {GpgME::CMS,
- {testKey("sender@example.net", GpgME::CMS)},
- {
- {QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
- {QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::CMS)}},
- }});
+ const KeyResolver::Solution expectedSolution = {
+ GpgME::CMS,
+ {testKey("sender@example.net", GpgME::CMS)},
+ {
+ {QStringLiteral("prefer-smime@example.net"), {testKey("Trusted S/MIME <prefer-smime@example.net>", GpgME::CMS)}},
+ {QStringLiteral("sender@example.net"), {testKey("sender@example.net", GpgME::CMS)}},
+ }};
+ verifySolution(dialog->result(), expectedSolution);
}
private:
std::shared_ptr<const KeyCache> mKeyCache;
};
QTEST_MAIN(NewKeyApprovalDialogTest)
#include "newkeyapprovaldialogtest.moc"

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 26, 6:59 PM (19 h, 8 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
19/18/e16bac177e6ad71361082357e54b

Event Timeline