File indexing completed on 2024-05-05 05:53:09

0001 /*
0002  * SPDX-License-Identifier: GPL-3.0-or-later
0003  * SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
0004  */
0005 #include "app/cli.h"
0006 
0007 #include "../test-utils/spy.h"
0008 
0009 #include <QSignalSpy>
0010 #include <QTest>
0011 #include <QThreadPool>
0012 #include <QtDebug>
0013 
0014 class CommandLineAccountJobTest: public QObject // clazy:exclude=ctor-missing-parent-argument
0015 {
0016     Q_OBJECT
0017 private Q_SLOTS:
0018     void initTestCase(void);
0019     void testValidAccountUri(void);
0020     void testInvalidAccountUri(void);
0021     void testExpiredRecipient(void);
0022 };
0023 
0024 void CommandLineAccountJobTest::initTestCase(void)
0025 {
0026     auto threadPool = QThreadPool::globalInstance();
0027     QVERIFY2(threadPool, "should have a global thread pool by now");
0028     threadPool->setMaxThreadCount(3);
0029 }
0030 
0031 void CommandLineAccountJobTest::testValidAccountUri(void)
0032 {
0033     model::AccountInput recipient;
0034     auto uut = new app::CommandLineAccountJob(&recipient);
0035 
0036     QSignalSpy invalid(uut, &app::CommandLineAccountJob::newAccountInvalid);
0037     QSignalSpy processed(uut, &app::CommandLineAccountJob::newAccountProcessed);
0038     QSignalSpy cleaned(uut, &QObject::destroyed);
0039 
0040     uut->run(QStringLiteral("otpauth://hotp/issuer:valid?secret=VALUE&digits=8&period=60&issuer=issuer&counter=42&algorithm=sha512"));
0041 
0042     QVERIFY2(test::signal_eventually_emitted_once(processed), "URI should be successfully processed by now");
0043     QVERIFY2(test::signal_eventually_emitted_once(cleaned), "AccountJob should be disposed of by now");
0044     QCOMPARE(invalid.count(), 0);
0045 
0046     QCOMPARE(recipient.name(), QStringLiteral("valid"));
0047     QCOMPARE(recipient.issuer(), QStringLiteral("issuer"));
0048     QCOMPARE(recipient.counter(), QStringLiteral("42"));
0049     QCOMPARE(recipient.secret(), QStringLiteral("VALUE==="));
0050     QCOMPARE(recipient.tokenLength(), 8U);
0051     QCOMPARE(recipient.timeStep(), 60U);
0052     QCOMPARE(recipient.type(), model::AccountInput::TokenType::Hotp);
0053     QCOMPARE(recipient.algorithm(), model::AccountInput::TOTPAlgorithm::Sha512);
0054 
0055     QVERIFY2(QThreadPool::globalInstance()->waitForDone(500), "the global thread pool should be done by now");
0056 }
0057 
0058 void CommandLineAccountJobTest::testExpiredRecipient(void)
0059 {
0060     auto recipient = new model::AccountInput();
0061     QSignalSpy expired(recipient, &QObject::destroyed);
0062 
0063     auto uut = new app::CommandLineAccountJob(recipient);
0064 
0065     QSignalSpy invalid(uut, &app::CommandLineAccountJob::newAccountInvalid);
0066     QSignalSpy processed(uut, &app::CommandLineAccountJob::newAccountProcessed);
0067     QSignalSpy cleaned(uut, &QObject::destroyed);
0068 
0069     recipient->deleteLater();
0070     QVERIFY2(test::signal_eventually_emitted_once(expired), "AccountInput should have expired by now");
0071 
0072     uut->run(QStringLiteral("otpauth://hotp/issuer:valid?secret=VALUE&digits=8&period=60&issuer=issuer&counter=42&algorithm=sha512"));
0073 
0074     QVERIFY2(test::signal_eventually_emitted_once(cleaned), "AccountJob should be disposed of by now");
0075     QCOMPARE(processed.count(), 0);
0076     QCOMPARE(invalid.count(), 0);
0077 
0078     QVERIFY2(QThreadPool::globalInstance()->waitForDone(500), "the global thread pool should be done by now");
0079 }
0080 
0081 void CommandLineAccountJobTest::testInvalidAccountUri(void)
0082 {
0083     model::AccountInput recipient;
0084     auto uut = new app::CommandLineAccountJob(&recipient);
0085 
0086     QSignalSpy invalid(uut, &app::CommandLineAccountJob::newAccountInvalid);
0087     QSignalSpy processed(uut, &app::CommandLineAccountJob::newAccountProcessed);
0088     QSignalSpy cleaned(uut, &QObject::destroyed);
0089 
0090     uut->run(QStringLiteral("not a valid otpauth:// URI"));
0091 
0092     QVERIFY2(test::signal_eventually_emitted_once(invalid), "URI should be rejected by now");
0093     QVERIFY2(test::signal_eventually_emitted_once(cleaned), "AccountJob should be disposed of by now");
0094     QCOMPARE(processed.count(), 0);
0095 
0096     QCOMPARE(recipient.name(), QString());
0097     QCOMPARE(recipient.issuer(), QString());
0098     QCOMPARE(recipient.counter(), QStringLiteral("0"));
0099     QCOMPARE(recipient.secret(), QString());
0100     QCOMPARE(recipient.tokenLength(), 6U);
0101     QCOMPARE(recipient.timeStep(), 30U);
0102     QCOMPARE(recipient.type(), model::AccountInput::TokenType::Totp);
0103     QCOMPARE(recipient.algorithm(), model::AccountInput::TOTPAlgorithm::Sha1);
0104 
0105     QVERIFY2(QThreadPool::globalInstance()->waitForDone(500), "the global thread pool should be done by now");
0106 }
0107 
0108 QTEST_GUILESS_MAIN(CommandLineAccountJobTest)
0109 
0110 #include "commandline-account-job.moc"