diff --git a/autotests/keyselectioncombotest.cpp b/autotests/keyselectioncombotest.cpp index 557486698..b2fb07d38 100644 --- a/autotests/keyselectioncombotest.cpp +++ b/autotests/keyselectioncombotest.cpp @@ -1,216 +1,232 @@ /* autotests/keyselectioncombotest.cpp This file is part of libkleopatra's test suite. SPDX-FileCopyrightText: 2021 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include #include #include #include #include #include #include using namespace Kleo; namespace { 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; } } 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->secret = 1; key->uids->validity = mapValidity(validity); 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 waitForKeySelectionComboBeingInitialized(const KeySelectionCombo *combo) { QVERIFY(combo); const auto spy = std::make_unique(combo, &KeySelectionCombo::keyListingFinished); QVERIFY(spy->isValid()); QVERIFY(spy->wait(10)); } } class KeySelectionComboTest : public QObject { Q_OBJECT private Q_SLOTS: + void initTestCase() + { + // force C locale for sorting + QLocale::setDefault(QLocale::c()); + } + 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("CN=,EMAIL=sender@example.net", GpgME::CMS, KeyCache::KeyCache::KeyUsage::AnyUsage), createTestKey("Full Trust ", GpgME::OpenPGP, KeyCache::KeyCache::KeyUsage::Encrypt), - createTestKey("Trusted S/MIME ", GpgME::CMS, KeyCache::KeyCache::KeyUsage::Encrypt), + createTestKey("CN=Trusted S/MIME,EMAIL=prefer-smime@example.net", GpgME::CMS, KeyCache::KeyCache::KeyUsage::Encrypt), createTestKey("Marginal Validity ", GpgME::OpenPGP, KeyCache::KeyCache::KeyUsage::Encrypt, GpgME::UserID::Marginal), }); } void cleanup() { // verify that nobody else holds a reference to the key cache QVERIFY(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 ", GpgME::OpenPGP).isNull()); QVERIFY(!testKey("Trusted S/MIME ", GpgME::CMS).isNull()); QVERIFY(!testKey("Marginal Validity ", GpgME::OpenPGP).isNull()); } + void test__certificates_are_sorted_alphabetically() + { + const auto combo = std::make_unique(); + waitForKeySelectionComboBeingInitialized(combo.get()); + QCOMPARE(combo->itemText(0).left(combo->itemText(0).indexOf(" (")), "Full Trust "); + QCOMPARE(combo->itemText(1).left(combo->itemText(1).indexOf(" (")), "Marginal Validity "); + QCOMPARE(combo->itemText(2).left(combo->itemText(2).indexOf(" (")), "Trusted S/MIME "); + // we don't check the order of the two "sender@example.net" keys + } + void test__after_initialization_default_key_is_current_key() { const auto combo = std::make_unique(); - combo->setDefaultKey(QString::fromLatin1(testKey("Full Trust ", GpgME::OpenPGP).primaryFingerprint())); + combo->setDefaultKey(QString::fromLatin1(testKey("Marginal Validity ", GpgME::OpenPGP).primaryFingerprint())); waitForKeySelectionComboBeingInitialized(combo.get()); - QCOMPARE(combo->currentKey().primaryFingerprint(), testKey("Full Trust ", GpgME::OpenPGP).primaryFingerprint()); + QCOMPARE(combo->currentKey().primaryFingerprint(), testKey("Marginal Validity ", GpgME::OpenPGP).primaryFingerprint()); } void test__currently_selected_key_is_retained_if_cache_is_updated() { const auto combo = std::make_unique(); - combo->setDefaultKey(QString::fromLatin1(testKey("Full Trust ", GpgME::OpenPGP).primaryFingerprint())); + combo->setDefaultKey(QString::fromLatin1(testKey("Marginal Validity ", GpgME::OpenPGP).primaryFingerprint())); waitForKeySelectionComboBeingInitialized(combo.get()); - combo->setCurrentIndex(3); + combo->setCurrentKey(testKey("Trusted S/MIME ", GpgME::CMS)); QCOMPARE(combo->currentKey().primaryFingerprint(), testKey("Trusted S/MIME ", GpgME::CMS).primaryFingerprint()); Q_EMIT KeyCache::mutableInstance()->keyListingDone(GpgME::KeyListResult{}); QCOMPARE(combo->currentKey().primaryFingerprint(), testKey("Trusted S/MIME ", GpgME::CMS).primaryFingerprint()); } void test__default_key_is_selected_if_currently_selected_key_is_gone_after_model_update() { const auto combo = std::make_unique(); combo->setDefaultKey(QString::fromLatin1(testKey("Full Trust ", GpgME::OpenPGP).primaryFingerprint())); waitForKeySelectionComboBeingInitialized(combo.get()); - combo->setCurrentIndex(3); + combo->setCurrentKey(testKey("Trusted S/MIME ", GpgME::CMS)); QCOMPARE(combo->currentKey().primaryFingerprint(), testKey("Trusted S/MIME ", GpgME::CMS).primaryFingerprint()); KeyCache::mutableInstance()->setKeys({ testKey("sender@example.net", GpgME::OpenPGP), testKey("sender@example.net", GpgME::CMS), testKey("Full Trust ", GpgME::OpenPGP), testKey("Marginal Validity ", GpgME::OpenPGP), }); QCOMPARE(combo->currentKey().primaryFingerprint(), testKey("Full Trust ", GpgME::OpenPGP).primaryFingerprint()); } void test__currently_selected_custom_item_is_retained_if_cache_is_updated() { const auto combo = std::make_unique(); combo->prependCustomItem({}, {}, QStringLiteral("custom1")); combo->appendCustomItem({}, {}, QStringLiteral("custom2")); combo->setDefaultKey(QString::fromLatin1(testKey("Full Trust ", GpgME::OpenPGP).primaryFingerprint())); waitForKeySelectionComboBeingInitialized(combo.get()); combo->setCurrentIndex(combo->count() - 1); QCOMPARE(combo->currentData(), QStringLiteral("custom2")); Q_EMIT KeyCache::mutableInstance()->keyListingDone(GpgME::KeyListResult{}); QCOMPARE(combo->currentData(), QStringLiteral("custom2")); } void test__default_key_is_selected_if_currently_selected_custom_item_is_gone_after_model_update() { const auto combo = std::make_unique(); combo->prependCustomItem({}, {}, QStringLiteral("custom1")); combo->appendCustomItem({}, {}, QStringLiteral("custom2")); combo->setDefaultKey(QString::fromLatin1(testKey("Full Trust ", GpgME::OpenPGP).primaryFingerprint())); waitForKeySelectionComboBeingInitialized(combo.get()); combo->setCurrentIndex(combo->count() - 1); QCOMPARE(combo->currentData(), QStringLiteral("custom2")); combo->removeCustomItem(QStringLiteral("custom2")); QCOMPARE(combo->currentKey().primaryFingerprint(), testKey("Full Trust ", GpgME::OpenPGP).primaryFingerprint()); } private: std::shared_ptr mKeyCache; }; QTEST_MAIN(KeySelectionComboTest) #include "keyselectioncombotest.moc"