LCOV - code coverage report
Current view: top level - lang/qt/tests - t-tofuinfo.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 202 282 71.6 %
Date: 2017-03-02 17:11:10 Functions: 27 44 61.4 %

          Line data    Source code
       1             : /* t-tofuinfo.cpp
       2             : 
       3             :     This file is part of qgpgme, the Qt API binding for gpgme
       4             :     Copyright (c) 2016 Intevation GmbH
       5             : 
       6             :     QGpgME is free software; you can redistribute it and/or
       7             :     modify it under the terms of the GNU General Public License as
       8             :     published by the Free Software Foundation; either version 2 of the
       9             :     License, or (at your option) any later version.
      10             : 
      11             :     QGpgME is distributed in the hope that it will be useful,
      12             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :     General Public License for more details.
      15             : 
      16             :     You should have received a copy of the GNU General Public License
      17             :     along with this program; if not, write to the Free Software
      18             :     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
      19             : 
      20             :     In addition, as a special exception, the copyright holders give
      21             :     permission to link the code of this program with any edition of
      22             :     the Qt library by Trolltech AS, Norway (or with modified versions
      23             :     of Qt that use the same license as Qt), and distribute linked
      24             :     combinations including the two.  You must obey the GNU General
      25             :     Public License in all respects for all of the code used other than
      26             :     Qt.  If you modify this file, you may extend this exception to
      27             :     your version of the file, but you are not obligated to do so.  If
      28             :     you do not wish to do so, delete this exception statement from
      29             :     your version.
      30             : */
      31             : #ifdef HAVE_CONFIG_H
      32             :  #include "config.h"
      33             : #endif
      34             : 
      35             : #include <QDebug>
      36             : #include <QTest>
      37             : #include <QTemporaryDir>
      38             : #include <QSignalSpy>
      39             : 
      40             : #include "protocol.h"
      41             : #include "tofuinfo.h"
      42             : #include "tofupolicyjob.h"
      43             : #include "verifyopaquejob.h"
      44             : #include "verificationresult.h"
      45             : #include "signingresult.h"
      46             : #include "importjob.h"
      47             : #include "importresult.h"
      48             : #include "keylistjob.h"
      49             : #include "keylistresult.h"
      50             : #include "qgpgmesignjob.h"
      51             : #include "key.h"
      52             : #include "t-support.h"
      53             : #include "engineinfo.h"
      54             : #include <iostream>
      55             : 
      56             : using namespace QGpgME;
      57             : using namespace GpgME;
      58             : 
      59             : static const char testMsg1[] =
      60             : "-----BEGIN PGP MESSAGE-----\n"
      61             : "\n"
      62             : "owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n"
      63             : "GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n"
      64             : "y1kvP4y+8D5a11ang0udywsA\n"
      65             : "=Crq6\n"
      66             : "-----END PGP MESSAGE-----\n";
      67             : 
      68             : static const char conflictKey1[] = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
      69             : "\n"
      70             : "mDMEWG+w/hYJKwYBBAHaRw8BAQdAiq1oStvDYg8ZfFs5DgisYJo8dJxD+C/AA21O\n"
      71             : "K/aif0O0GXRvZnVfY29uZmxpY3RAZXhhbXBsZS5jb22IlgQTFggAPhYhBHoJBLaV\n"
      72             : "DamYAgoa1L5BwMOl/x88BQJYb7D+AhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMB\n"
      73             : "Ah4BAheAAAoJEL5BwMOl/x88GvwA/0SxkbLyAcshGm2PRrPsFQsSVAfwaSYFVmS2\n"
      74             : "cMVIw1PfAQDclRH1Z4MpufK07ju4qI33o4s0UFpVRBuSxt7A4P2ZD7g4BFhvsP4S\n"
      75             : "CisGAQQBl1UBBQEBB0AmVrgaDNJ7K2BSalsRo2EkRJjHGqnp5bBB0tapnF81CQMB\n"
      76             : "CAeIeAQYFggAIBYhBHoJBLaVDamYAgoa1L5BwMOl/x88BQJYb7D+AhsMAAoJEL5B\n"
      77             : "wMOl/x88OR0BAMq4/vmJUORRTmzjHcv/DDrQB030DSq666rlckGIKTShAPoDXM9N\n"
      78             : "0gZK+YzvrinSKZXHmn0aSwmC1/hyPybJPEljBw==\n"
      79             : "=p2Oj\n"
      80             : "-----END PGP PUBLIC KEY BLOCK-----\n";
      81             : 
      82             : static const char conflictKey2[] = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
      83             : "\n"
      84             : "mDMEWG+xShYJKwYBBAHaRw8BAQdA567gPEPJRpqKnZjlFJMRNUqruRviYMyygfF6\n"
      85             : "6Ok+ygu0GXRvZnVfY29uZmxpY3RAZXhhbXBsZS5jb22IlgQTFggAPhYhBJ5kRh7E\n"
      86             : "I98w8kgUcmkAfYFvqqHsBQJYb7FKAhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMB\n"
      87             : "Ah4BAheAAAoJEGkAfYFvqqHsYR0BAOz8JjYB4VvGkt6noLS3F5TLfsedGwQkBCw5\n"
      88             : "znw/vGZsAQD9DSX+ekwdrN56mNO8ISt5uVS7B1ZQtouNBF+nzcwbDbg4BFhvsUoS\n"
      89             : "CisGAQQBl1UBBQEBB0BFupW8+Xc1ikab8TJqANjQhvFVh6uLsgcK4g9lZgbGXAMB\n"
      90             : "CAeIeAQYFggAIBYhBJ5kRh7EI98w8kgUcmkAfYFvqqHsBQJYb7FKAhsMAAoJEGkA\n"
      91             : "fYFvqqHs15ABALdN3uiV/07cJ3RkNb3WPcijGsto+lECDS11dKEwTMFeAQDx+V36\n"
      92             : "ocbYC/xEuwi3w45oNqGieazzcD/GBbt8OBk3BA==\n"
      93             : "=45IR\n"
      94             : "-----END PGP PUBLIC KEY BLOCK-----\n";
      95             : 
      96             : static const char conflictMsg1[] = "-----BEGIN PGP MESSAGE-----\n"
      97             : "\n"
      98             : "owGbwMvMwCG2z/HA4aX/5W0YT3MlMUTkb2xPSizi6ihlYRDjYJAVU2Sp4mTZNpV3\n"
      99             : "5QwmLqkrMLWsTCCFDFycAjCR1vcMf4U0Qrs6qzqfHJ9puGOFduLN2nVmhsumxjBE\n"
     100             : "mdw4lr1ehIWR4QdLuNBpe86PGx1PtNXfVAzm/hu+vfjCp5BVNjPTM9L0eAA=\n"
     101             : "=MfBD\n"
     102             : "-----END PGP MESSAGE-----\n";
     103             : 
     104             : static const char conflictMsg2[] = "-----BEGIN PGP MESSAGE-----\n"
     105             : "\n"
     106             : "owGbwMvMwCGWyVDbmL9q4RvG01xJDBH5GyvS8vO5OkpZGMQ4GGTFFFnmpbjJHVG+\n"
     107             : "b/DJQ6QIppaVCaSQgYtTACaySZHhr/SOPrdFJ89KrcwKY5i1XnflXYf2PK76SafK\n"
     108             : "tkxXuXzvJAvDX4kCybuqFk3HXCexz2+IrnZ+5X5EqOnuo3ens2cte+uzlhMA\n"
     109             : "=BIAi\n"
     110             : "-----END PGP MESSAGE-----\n";
     111             : 
     112           2 : class TofuInfoTest: public QGpgMETest
     113             : {
     114             :     Q_OBJECT
     115             : Q_SIGNALS:
     116             :     void asyncDone();
     117             : 
     118             : private:
     119           5 :     bool testSupported()
     120             :     {
     121           5 :         return !(GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.16");
     122             :     }
     123             : 
     124           1 :     void testTofuCopy(TofuInfo other, const TofuInfo &orig)
     125             :     {
     126           1 :         QVERIFY(!orig.isNull());
     127           1 :         QVERIFY(!other.isNull());
     128           1 :         QVERIFY(orig.signLast() == other.signLast());
     129           1 :         QVERIFY(orig.signCount() == other.signCount());
     130           1 :         QVERIFY(orig.validity() == other.validity());
     131           1 :         QVERIFY(orig.policy() == other.policy());
     132             :     }
     133             : 
     134           6 :     void signAndVerify(const QString &what, const GpgME::Key &key, int expected)
     135             :     {
     136           6 :         Context *ctx = Context::createForProtocol(OpenPGP);
     137          12 :         TestPassphraseProvider provider;
     138           6 :         ctx->setPassphraseProvider(&provider);
     139           6 :         ctx->setPinentryMode(Context::PinentryLoopback);
     140           6 :         auto *job = new QGpgMESignJob(ctx);
     141             : 
     142          12 :         std::vector<Key> keys;
     143           6 :         keys.push_back(key);
     144          12 :         QByteArray signedData;
     145          12 :         auto sigResult = job->exec(keys, what.toUtf8(), NormalSignatureMode, signedData);
     146           6 :         delete job;
     147             : 
     148           6 :         QVERIFY(!sigResult.error());
     149          12 :         foreach (const auto uid, keys[0].userIDs()) {
     150          12 :             auto info = uid.tofuInfo();
     151           6 :             QVERIFY(info.signCount() == expected - 1);
     152             :         }
     153             : 
     154           6 :         auto verifyJob = openpgp()->verifyOpaqueJob();
     155          12 :         QByteArray verified;
     156             : 
     157          12 :         auto result = verifyJob->exec(signedData, verified);
     158           6 :         delete verifyJob;
     159             : 
     160           6 :         QVERIFY(!result.error());
     161           6 :         QVERIFY(verified == what.toUtf8());
     162             : 
     163           6 :         QVERIFY(result.numSignatures() == 1);
     164          12 :         auto sig = result.signatures()[0];
     165             : 
     166          12 :         auto key2 = sig.key();
     167           6 :         QVERIFY(!key.isNull());
     168           6 :         QVERIFY(!strcmp (key2.primaryFingerprint(), key.primaryFingerprint()));
     169           6 :         QVERIFY(!strcmp (key.primaryFingerprint(), sig.fingerprint()));
     170          12 :         auto stats = key2.userID(0).tofuInfo();
     171           6 :         QVERIFY(!stats.isNull());
     172           6 :         if (stats.signCount() != expected) {
     173           0 :             std::cout << "################ Key before verify: "
     174           0 :                       << key
     175           0 :                       << "################ Key after verify: "
     176           0 :                       << key2;
     177             :         }
     178           6 :         QVERIFY(stats.signCount() == expected);
     179             :     }
     180             : 
     181             : private Q_SLOTS:
     182           1 :     void testTofuNull()
     183             :     {
     184           1 :         if (!testSupported()) {
     185           0 :             return;
     186             :         }
     187           2 :         TofuInfo tofu;
     188           1 :         QVERIFY(tofu.isNull());
     189           1 :         QVERIFY(!tofu.description());
     190           1 :         QVERIFY(!tofu.signCount());
     191           1 :         QVERIFY(!tofu.signLast());
     192           1 :         QVERIFY(!tofu.signFirst());
     193           1 :         QVERIFY(tofu.validity() == TofuInfo::ValidityUnknown);
     194           1 :         QVERIFY(tofu.policy() == TofuInfo::PolicyUnknown);
     195             :     }
     196             : 
     197           1 :     void testTofuInfo()
     198             :     {
     199           1 :         if (!testSupported()) {
     200           0 :             return;
     201             :         }
     202           1 :         auto *job = openpgp()->verifyOpaqueJob(true);
     203           2 :         const QByteArray data1(testMsg1);
     204           2 :         QByteArray plaintext;
     205             : 
     206           1 :         auto ctx = Job::context(job);
     207           1 :         QVERIFY(ctx);
     208           1 :         ctx->setSender("alfa@example.net");
     209             : 
     210           2 :         auto result = job->exec(data1, plaintext);
     211           1 :         delete job;
     212             : 
     213           1 :         QVERIFY(!result.isNull());
     214           1 :         QVERIFY(!result.error());
     215           1 :         QVERIFY(!strcmp(plaintext.constData(), "Just GNU it!\n"));
     216             : 
     217           1 :         QVERIFY(result.numSignatures() == 1);
     218           2 :         Signature sig = result.signatures()[0];
     219             :         /* TOFU is always marginal */
     220           1 :         QVERIFY(sig.validity() == Signature::Marginal);
     221             : 
     222           2 :         auto stats = sig.key().userID(0).tofuInfo();
     223           1 :         QVERIFY(!stats.isNull());
     224           1 :         QVERIFY(sig.key().primaryFingerprint());
     225           1 :         QVERIFY(sig.fingerprint());
     226           1 :         QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
     227           1 :         QVERIFY(stats.signFirst() == stats.signLast());
     228           1 :         QVERIFY(stats.signCount() == 1);
     229           1 :         QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
     230           1 :         QVERIFY(stats.validity() == TofuInfo::LittleHistory);
     231             : 
     232           1 :         testTofuCopy(stats, stats);
     233             : 
     234             :         /* Another verify */
     235             : 
     236           1 :         job = openpgp()->verifyOpaqueJob(true);
     237           1 :         result = job->exec(data1, plaintext);
     238           1 :         delete job;
     239             : 
     240           1 :         QVERIFY(!result.isNull());
     241           1 :         QVERIFY(!result.error());
     242             : 
     243           1 :         QVERIFY(result.numSignatures() == 1);
     244           1 :         sig = result.signatures()[0];
     245             :         /* TOFU is always marginal */
     246           1 :         QVERIFY(sig.validity() == Signature::Marginal);
     247             : 
     248           1 :         stats = sig.key().userID(0).tofuInfo();
     249           1 :         QVERIFY(!stats.isNull());
     250           1 :         QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
     251           1 :         QVERIFY(stats.signFirst() == stats.signLast());
     252           1 :         QVERIFY(stats.signCount() == 1);
     253           1 :         QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
     254           1 :         QVERIFY(stats.validity() == TofuInfo::LittleHistory);
     255             : 
     256             :         /* Verify that another call yields the same result */
     257           1 :         job = openpgp()->verifyOpaqueJob(true);
     258           1 :         result = job->exec(data1, plaintext);
     259           1 :         delete job;
     260             : 
     261           1 :         QVERIFY(!result.isNull());
     262           1 :         QVERIFY(!result.error());
     263             : 
     264           1 :         QVERIFY(result.numSignatures() == 1);
     265           1 :         sig = result.signatures()[0];
     266             :         /* TOFU is always marginal */
     267           1 :         QVERIFY(sig.validity() == Signature::Marginal);
     268             : 
     269           1 :         stats = sig.key().userID(0).tofuInfo();
     270           1 :         QVERIFY(!stats.isNull());
     271           1 :         QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
     272           1 :         QVERIFY(stats.signFirst() == stats.signLast());
     273           1 :         QVERIFY(stats.signCount() == 1);
     274           1 :         QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
     275           1 :         QVERIFY(stats.validity() == TofuInfo::LittleHistory);
     276             :     }
     277             : 
     278           1 :     void testTofuSignCount()
     279             :     {
     280           1 :         if (!testSupported()) {
     281           0 :             return;
     282             :         }
     283           1 :         auto *job = openpgp()->keyListJob(false, false, false);
     284           1 :         job->addMode(GpgME::WithTofu);
     285           2 :         std::vector<GpgME::Key> keys;
     286           3 :         GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
     287           3 :                                                 true, keys);
     288           1 :         delete job;
     289           1 :         QVERIFY(!keys.empty());
     290           2 :         Key key = keys[0];
     291           1 :         QVERIFY(!key.isNull());
     292             : 
     293             :         /* As we sign & verify quickly here we need different
     294             :          * messages to avoid having them treated as the same
     295             :          * message if they were created within the same second.
     296             :          * Alternatively we could use the same message and wait
     297             :          * a second between each call. But this would slow down
     298             :          * the testsuite. */
     299           2 :         signAndVerify(QStringLiteral("Hello"), key, 1);
     300           1 :         key.update();
     301           2 :         signAndVerify(QStringLiteral("Hello2"), key, 2);
     302           1 :         key.update();
     303           2 :         signAndVerify(QStringLiteral("Hello3"), key, 3);
     304           1 :         key.update();
     305           2 :         signAndVerify(QStringLiteral("Hello4"), key, 4);
     306             :     }
     307             : 
     308           1 :     void testTofuKeyList()
     309             :     {
     310           1 :         if (!testSupported()) {
     311           0 :             return;
     312             :         }
     313             : 
     314             :         /* First check that the key has no tofu info. */
     315           1 :         auto *job = openpgp()->keyListJob(false, false, false);
     316           2 :         std::vector<GpgME::Key> keys;
     317           3 :         auto result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
     318           3 :                                                  true, keys);
     319           1 :         delete job;
     320           1 :         QVERIFY(!keys.empty());
     321           2 :         auto key = keys[0];
     322           1 :         QVERIFY(!key.isNull());
     323           1 :         QVERIFY(key.userID(0).tofuInfo().isNull());
     324           2 :         auto keyCopy = key;
     325           1 :         keyCopy.update();
     326           1 :         auto sigCnt = keyCopy.userID(0).tofuInfo().signCount();
     327           3 :         signAndVerify(QStringLiteral("Hello5"), keyCopy,
     328           1 :                       sigCnt + 1);
     329           1 :         keyCopy.update();
     330           3 :         signAndVerify(QStringLiteral("Hello6"), keyCopy,
     331           1 :                       sigCnt + 2);
     332             : 
     333             :         /* Now another one but with tofu */
     334           1 :         job = openpgp()->keyListJob(false, false, false);
     335           1 :         job->addMode(GpgME::WithTofu);
     336           3 :         result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
     337           2 :                            true, keys);
     338           1 :         delete job;
     339           1 :         QVERIFY(!result.error());
     340           1 :         QVERIFY(!keys.empty());
     341           2 :         auto key2 = keys[0];
     342           1 :         QVERIFY(!key2.isNull());
     343           2 :         auto info = key2.userID(0).tofuInfo();
     344           1 :         QVERIFY(!info.isNull());
     345           1 :         QVERIFY(info.signCount());
     346             :     }
     347             : 
     348           1 :     void testTofuPolicy()
     349             :     {
     350           1 :         if (!testSupported()) {
     351           0 :             return;
     352             :         }
     353             : 
     354             :         /* First check that the key has no tofu info. */
     355           1 :         auto *job = openpgp()->keyListJob(false, false, false);
     356           2 :         std::vector<GpgME::Key> keys;
     357           1 :         job->addMode(GpgME::WithTofu);
     358           3 :         auto result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
     359           3 :                                                  false, keys);
     360             : 
     361           1 :         if (keys.empty()) {
     362           0 :             qDebug() << "bravo@example.net not found";
     363           0 :             qDebug() << "Error: " << result.error().asString();
     364           0 :             const auto homedir = QString::fromLocal8Bit(qgetenv("GNUPGHOME"));
     365           0 :             qDebug() << "Homedir is: " << homedir;
     366           0 :             QFileInfo fi(homedir + "/pubring.gpg");
     367           0 :             qDebug () << "pubring exists: " << fi.exists() << " readable? "
     368           0 :                       << fi.isReadable() << " size: " << fi.size();
     369           0 :             QFileInfo fi2(homedir + "/pubring.kbx");
     370           0 :             qDebug () << "keybox exists: " << fi2.exists() << " readable? "
     371           0 :                       << fi2.isReadable() << " size: " << fi2.size();
     372             : 
     373           0 :             result = job->exec(QStringList(), false, keys);
     374           0 :             foreach (const auto key, keys) {
     375           0 :                 qDebug() << "Key: " << key.userID(0).name() << " <"
     376           0 :                          << key.userID(0).email()
     377           0 :                          << ">\n fpr: " << key.primaryFingerprint();
     378             :             }
     379             :         }
     380           1 :         QVERIFY(!result.error());
     381           1 :         QVERIFY(!keys.empty());
     382           2 :         auto key = keys[0];
     383           1 :         QVERIFY(!key.isNull());
     384           1 :         QVERIFY(key.userID(0).tofuInfo().policy() != TofuInfo::PolicyBad);
     385           1 :         auto *tofuJob = openpgp()->tofuPolicyJob();
     386           2 :         auto err = tofuJob->exec(key, TofuInfo::PolicyBad);
     387           1 :         QVERIFY(!err);
     388           3 :         result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
     389           2 :                                             false, keys);
     390           1 :         QVERIFY(!keys.empty());
     391           1 :         key = keys[0];
     392           1 :         QVERIFY(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyBad);
     393           1 :         err = tofuJob->exec(key, TofuInfo::PolicyGood);
     394             : 
     395           3 :         result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
     396           2 :                                             false, keys);
     397           1 :         key = keys[0];
     398           1 :         QVERIFY(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyGood);
     399           1 :         delete tofuJob;
     400           1 :         delete job;
     401             :     }
     402             : 
     403           1 :     void testTofuConflict()
     404             :     {
     405           1 :         if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.19") {
     406           2 :             return;
     407             :         }
     408             : 
     409             :         // Import key 1
     410           0 :         auto importjob = openpgp()->importJob();
     411             :         connect(importjob, &ImportJob::result, this,
     412           0 :                 [this](ImportResult result, QString, Error)
     413           0 :         {
     414           0 :             QVERIFY(!result.error());
     415           0 :             QVERIFY(!result.imports().empty());
     416           0 :             QVERIFY(result.numImported());
     417           0 :             Q_EMIT asyncDone();
     418           0 :         });
     419           0 :         importjob->start(QByteArray(conflictKey1));
     420           0 :         QSignalSpy spy (this, SIGNAL(asyncDone()));
     421           0 :         QVERIFY(spy.wait());
     422             : 
     423             :         // Verify Message 1
     424           0 :         const QByteArray signedData(conflictMsg1);
     425           0 :         auto verifyJob = openpgp()->verifyOpaqueJob(true);
     426           0 :         QByteArray verified;
     427           0 :         auto result = verifyJob->exec(signedData, verified);
     428           0 :         delete verifyJob;
     429             : 
     430           0 :         QVERIFY(!result.isNull());
     431           0 :         QVERIFY(!result.error());
     432             : 
     433           0 :         QVERIFY(result.numSignatures() == 1);
     434           0 :         auto sig = result.signatures()[0];
     435           0 :         QVERIFY(sig.validity() == Signature::Marginal);
     436             : 
     437           0 :         auto stats = sig.key().userID(0).tofuInfo();
     438           0 :         QVERIFY(!stats.isNull());
     439           0 :         QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
     440           0 :         QVERIFY(stats.signFirst() == stats.signLast());
     441           0 :         QVERIFY(stats.signCount() == 1);
     442           0 :         QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
     443           0 :         QVERIFY(stats.validity() == TofuInfo::LittleHistory);
     444             : 
     445             :         // Import key 2
     446           0 :         importjob = openpgp()->importJob();
     447             :         connect(importjob, &ImportJob::result, this,
     448           0 :                 [this](ImportResult result, QString, Error)
     449           0 :         {
     450           0 :             QVERIFY(!result.error());
     451           0 :             QVERIFY(!result.imports().empty());
     452           0 :             QVERIFY(result.numImported());
     453           0 :             Q_EMIT asyncDone();
     454           0 :         });
     455           0 :         importjob->start(QByteArray(conflictKey2));
     456           0 :         QSignalSpy spy2 (this, SIGNAL(asyncDone()));
     457           0 :         QVERIFY(spy2.wait());
     458             : 
     459             :         // Verify Message 2
     460           0 :         const QByteArray signedData2(conflictMsg2);
     461           0 :         QByteArray verified2;
     462           0 :         verifyJob = openpgp()->verifyOpaqueJob(true);
     463           0 :         result = verifyJob->exec(signedData2, verified2);
     464           0 :         delete verifyJob;
     465             : 
     466           0 :         QVERIFY(!result.isNull());
     467           0 :         QVERIFY(!result.error());
     468             : 
     469           0 :         QVERIFY(result.numSignatures() == 1);
     470           0 :         sig = result.signatures()[0];
     471           0 :         QVERIFY(sig.validity() == Signature::Unknown);
     472             :         // TODO activate when implemented
     473             :         // QVERIFY(sig.summary() == Signature::TofuConflict);
     474             : 
     475           0 :         stats = sig.key().userID(0).tofuInfo();
     476           0 :         QVERIFY(!stats.isNull());
     477           0 :         QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
     478           0 :         QVERIFY(stats.signFirst() == stats.signLast());
     479           0 :         QVERIFY(stats.signCount() == 1);
     480           0 :         QVERIFY(stats.policy() == TofuInfo::PolicyAsk);
     481           0 :         QVERIFY(stats.validity() == TofuInfo::Conflict);
     482             :     }
     483             : 
     484             : 
     485           1 :     void initTestCase()
     486             :     {
     487           1 :         QGpgMETest::initTestCase();
     488           2 :         const QString gpgHome = qgetenv("GNUPGHOME");
     489           1 :         qputenv("GNUPGHOME", mDir.path().toUtf8());
     490           1 :         QVERIFY(mDir.isValid());
     491           3 :         QFile conf(mDir.path() + QStringLiteral("/gpg.conf"));
     492           1 :         QVERIFY(conf.open(QIODevice::WriteOnly));
     493           1 :         conf.write("trust-model tofu+pgp");
     494           1 :         conf.close();
     495           3 :         QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf"));
     496           1 :         QVERIFY(agentConf.open(QIODevice::WriteOnly));
     497           1 :         agentConf.write("allow-loopback-pinentry");
     498           1 :         agentConf.close();
     499           1 :         QVERIFY(copyKeyrings(gpgHome, mDir.path()));
     500             :     }
     501             : private:
     502             :     QTemporaryDir mDir;
     503             : 
     504             : };
     505             : 
     506           1 : QTEST_MAIN(TofuInfoTest)
     507             : 
     508             : #include "t-tofuinfo.moc"

Generated by: LCOV version 1.13