LCOV - code coverage report
Current view: top level - lang/qt/tests - t-encrypt.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 98 100 98.0 %
Date: 2016-11-29 15:07:43 Functions: 15 22 68.2 %

          Line data    Source code
       1             : /* t-encrypt.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             : #include <QBuffer>
      40             : #include "keylistjob.h"
      41             : #include "encryptjob.h"
      42             : #include "qgpgmeencryptjob.h"
      43             : #include "encryptionresult.h"
      44             : #include "decryptionresult.h"
      45             : #include "qgpgmedecryptjob.h"
      46             : #include "qgpgmebackend.h"
      47             : #include "keylistresult.h"
      48             : #include "engineinfo.h"
      49             : #include "t-support.h"
      50             : 
      51             : #define PROGRESS_TEST_SIZE 1 * 1024 * 1024
      52             : 
      53             : using namespace QGpgME;
      54             : using namespace GpgME;
      55             : 
      56           2 : static bool decryptSupported()
      57             : {
      58             :     /* With GnuPG 2.0.x (at least 2.0.26 by default on jessie)
      59             :      * the passphrase_cb does not work. So the test popped up
      60             :      * a pinentry. So tests requiring decryption don't work. */
      61           2 :     static auto version = GpgME::engineInfo(GpgME::GpgEngine).engineVersion();
      62           2 :     if (version < "2.0.0") {
      63             :         /* With 1.4 it just works */
      64           0 :         return true;
      65             :     }
      66           2 :     if (version < "2.1.0") {
      67             :         /* With 2.1 it works with loopback mode */
      68           0 :         return false;
      69             :     }
      70           2 :     return true;
      71             : }
      72             : 
      73           2 : class EncryptionTest : public QGpgMETest
      74             : {
      75             :     Q_OBJECT
      76             : 
      77             : Q_SIGNALS:
      78             :     void asyncDone();
      79             : 
      80             : private Q_SLOTS:
      81             : 
      82           1 :     void testSimpleEncryptDecrypt()
      83             :     {
      84           1 :         auto listjob = openpgp()->keyListJob(false, false, false);
      85           1 :         std::vector<Key> keys;
      86           3 :         auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"),
      87           3 :                                           false, keys);
      88           1 :         Q_ASSERT(!keylistresult.error());
      89           1 :         Q_ASSERT(keys.size() == 1);
      90           1 :         delete listjob;
      91             : 
      92           1 :         auto job = openpgp()->encryptJob(/*ASCII Armor */true, /* Textmode */ true);
      93           1 :         Q_ASSERT(job);
      94           2 :         QByteArray cipherText;
      95           3 :         auto result = job->exec(keys, QStringLiteral("Hello World").toUtf8(), Context::AlwaysTrust, cipherText);
      96           1 :         delete job;
      97           1 :         Q_ASSERT(!result.error());
      98           2 :         const auto cipherString = QString::fromUtf8(cipherText);
      99           1 :         Q_ASSERT(cipherString.startsWith("-----BEGIN PGP MESSAGE-----"));
     100             : 
     101             :         /* Now decrypt */
     102           1 :         if (!decryptSupported()) {
     103           1 :             return;
     104             :         }
     105           1 :         auto ctx = Context::createForProtocol(OpenPGP);
     106           2 :         TestPassphraseProvider provider;
     107           1 :         ctx->setPassphraseProvider(&provider);
     108           1 :         ctx->setPinentryMode(Context::PinentryLoopback);
     109           1 :         auto decJob = new QGpgMEDecryptJob(ctx);
     110           2 :         QByteArray plainText;
     111           2 :         auto decResult = decJob->exec(cipherText, plainText);
     112           1 :         Q_ASSERT(!result.error());
     113           2 :         Q_ASSERT(QString::fromUtf8(plainText) == QStringLiteral("Hello World"));
     114           2 :         delete decJob;
     115             :     }
     116             : 
     117           1 :     void testProgress()
     118             :     {
     119           1 :         if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.15") {
     120             :             // We can only test the progress with 2.1.15 as this started to
     121             :             // have total progress for memory callbacks
     122           1 :             return;
     123             :         }
     124           1 :         auto listjob = openpgp()->keyListJob(false, false, false);
     125           1 :         std::vector<Key> keys;
     126           3 :         auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"),
     127           3 :                                           false, keys);
     128           1 :         Q_ASSERT(!keylistresult.error());
     129           1 :         Q_ASSERT(keys.size() == 1);
     130           1 :         delete listjob;
     131             : 
     132           1 :         auto job = openpgp()->encryptJob(/*ASCII Armor */false, /* Textmode */ false);
     133           1 :         Q_ASSERT(job);
     134           2 :         QByteArray plainBa;
     135           1 :         plainBa.fill('X', PROGRESS_TEST_SIZE);
     136           2 :         QByteArray cipherText;
     137             : 
     138           1 :         bool initSeen = false;
     139           1 :         bool finishSeen = false;
     140           2 :         connect(job, &Job::progress, this, [this, &initSeen, &finishSeen] (const QString&, int current, int total) {
     141             :                 // We only check for progress 0 and max progress as the other progress
     142             :                 // lines depend on the system speed and are as such unreliable to test.
     143           2 :                 Q_ASSERT(total == PROGRESS_TEST_SIZE);
     144           2 :                 if (current == 0) {
     145           1 :                     initSeen = true;
     146             :                 }
     147           2 :                 if (current == total) {
     148           1 :                     finishSeen = true;
     149             :                 }
     150           2 :                 Q_ASSERT(current >= 0 && current <= total);
     151           3 :             });
     152             :         connect(job, &EncryptJob::result, this, [this, &initSeen, &finishSeen] (const GpgME::EncryptionResult &,
     153             :                                                                                 const QByteArray &,
     154             :                                                                                 const QString,
     155           1 :                                                                                 const GpgME::Error) {
     156           1 :                 Q_ASSERT(initSeen);
     157           1 :                 Q_ASSERT(finishSeen);
     158           1 :                 Q_EMIT asyncDone();
     159           2 :             });
     160             : 
     161           2 :         auto inptr  = std::shared_ptr<QIODevice>(new QBuffer(&plainBa));
     162           1 :         inptr->open(QIODevice::ReadOnly);
     163           2 :         auto outptr = std::shared_ptr<QIODevice>(new QBuffer(&cipherText));
     164           1 :         outptr->open(QIODevice::WriteOnly);
     165             : 
     166           1 :         job->start(keys, inptr, outptr, Context::AlwaysTrust);
     167           2 :         QSignalSpy spy (this, SIGNAL(asyncDone()));
     168           2 :         Q_ASSERT(spy.wait());
     169             :     }
     170             : 
     171           1 :     void testSymmetricEncryptDecrypt()
     172             :     {
     173           1 :         if (!decryptSupported()) {
     174           1 :             return;
     175             :         }
     176           1 :         auto ctx = Context::createForProtocol(OpenPGP);
     177           1 :         TestPassphraseProvider provider;
     178           1 :         ctx->setPassphraseProvider(&provider);
     179           1 :         ctx->setPinentryMode(Context::PinentryLoopback);
     180           1 :         ctx->setArmor(true);
     181           1 :         ctx->setTextMode(true);
     182           1 :         auto job = new QGpgMEEncryptJob(ctx);
     183           2 :         QByteArray cipherText;
     184           3 :         auto result = job->exec(std::vector<Key>(), QStringLiteral("Hello symmetric World").toUtf8(), Context::AlwaysTrust, cipherText);
     185           1 :         delete job;
     186           1 :         Q_ASSERT(!result.error());
     187           2 :         const auto cipherString = QString::fromUtf8(cipherText);
     188           1 :         Q_ASSERT(cipherString.startsWith("-----BEGIN PGP MESSAGE-----"));
     189             : 
     190           1 :         killAgent(mDir.path());
     191             : 
     192           1 :         auto ctx2 = Context::createForProtocol(OpenPGP);
     193           1 :         ctx2->setPassphraseProvider(&provider);
     194           1 :         ctx2->setPinentryMode(Context::PinentryLoopback);
     195           1 :         auto decJob = new QGpgMEDecryptJob(ctx2);
     196           2 :         QByteArray plainText;
     197           2 :         auto decResult = decJob->exec(cipherText, plainText);
     198           1 :         Q_ASSERT(!result.error());
     199           2 :         Q_ASSERT(QString::fromUtf8(plainText) == QStringLiteral("Hello symmetric World"));
     200           2 :         delete decJob;
     201             :     }
     202             : 
     203             : private:
     204             :     /* Loopback and passphrase provider don't work for mixed encryption.
     205             :      * So this test is disabled until gnupg(?) is fixed for this. */
     206             :     void testMixedEncryptDecrypt()
     207             :     {
     208             :         if (!decryptSupported()) {
     209             :             return;
     210             :         }
     211             :         auto listjob = openpgp()->keyListJob(false, false, false);
     212             :         std::vector<Key> keys;
     213             :         auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"),
     214             :                                           false, keys);
     215             :         Q_ASSERT(!keylistresult.error());
     216             :         Q_ASSERT(keys.size() == 1);
     217             :         delete listjob;
     218             : 
     219             :         auto ctx = Context::createForProtocol(OpenPGP);
     220             :         ctx->setPassphraseProvider(new TestPassphraseProvider);
     221             :         ctx->setPinentryMode(Context::PinentryLoopback);
     222             :         ctx->setArmor(true);
     223             :         ctx->setTextMode(true);
     224             :         auto job = new QGpgMEEncryptJob(ctx);
     225             :         QByteArray cipherText;
     226             :         printf("Before exec, flags: %x\n", Context::Symmetric | Context::AlwaysTrust);
     227             :         auto result = job->exec(keys, QStringLiteral("Hello symmetric World").toUtf8(),
     228             :                                 static_cast<Context::EncryptionFlags>(Context::Symmetric | Context::AlwaysTrust),
     229             :                                 cipherText);
     230             :         printf("After exec\n");
     231             :         delete job;
     232             :         Q_ASSERT(!result.error());
     233             :         printf("Cipher:\n%s\n", cipherText.constData());
     234             :         const auto cipherString = QString::fromUtf8(cipherText);
     235             :         Q_ASSERT(cipherString.startsWith("-----BEGIN PGP MESSAGE-----"));
     236             : 
     237             :         killAgent(mDir.path());
     238             : 
     239             :         /* Now create a new homedir which with we test symetric decrypt. */
     240             :         QTemporaryDir tmp;
     241             :         qputenv("GNUPGHOME", tmp.path().toUtf8());
     242             :         QFile agentConf(tmp.path() + QStringLiteral("/gpg-agent.conf"));
     243             :         Q_ASSERT(agentConf.open(QIODevice::WriteOnly));
     244             :         agentConf.write("allow-loopback-pinentry");
     245             :         agentConf.close();
     246             : 
     247             :         auto ctx2 = Context::createForProtocol(OpenPGP);
     248             :         ctx2->setPassphraseProvider(new TestPassphraseProvider);
     249             :         ctx2->setPinentryMode(Context::PinentryLoopback);
     250             :         ctx2->setTextMode(true);
     251             :         auto decJob = new QGpgMEDecryptJob(ctx2);
     252             :         QByteArray plainText;
     253             :         auto decResult = decJob->exec(cipherText, plainText);
     254             :         Q_ASSERT(!decResult.error());
     255             :         qDebug() << "Plain: " << plainText;
     256             :         Q_ASSERT(QString::fromUtf8(plainText) == QStringLiteral("Hello symmetric World"));
     257             :         delete decJob;
     258             : 
     259             :         killAgent(tmp.path());
     260             :         qputenv("GNUPGHOME", mDir.path().toUtf8());
     261             :     }
     262             : 
     263             : public Q_SLOT:
     264             : 
     265             :     void initTestCase()
     266             :     {
     267             :         QGpgMETest::initTestCase();
     268             :         const QString gpgHome = qgetenv("GNUPGHOME");
     269             :         qputenv("GNUPGHOME", mDir.path().toUtf8());
     270             :         Q_ASSERT(mDir.isValid());
     271             :         QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf"));
     272             :         Q_ASSERT(agentConf.open(QIODevice::WriteOnly));
     273             :         agentConf.write("allow-loopback-pinentry");
     274             :         agentConf.close();
     275             :         Q_ASSERT(copyKeyrings(gpgHome, mDir.path()));
     276             :     }
     277             : 
     278             : private:
     279             :     QTemporaryDir mDir;
     280             : };
     281             : 
     282           1 : QTEST_MAIN(EncryptionTest)
     283             : 
     284             : #include "t-encrypt.moc"

Generated by: LCOV version 1.11