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 <QCoreApplication> 0010 #include <QSignalSpy> 0011 #include <QTest> 0012 #include <QThreadPool> 0013 #include <QtDebug> 0014 0015 class CommandLineOptionsTest: public QObject // clazy:exclude=ctor-missing-parent-argument 0016 { 0017 Q_OBJECT 0018 private Q_SLOTS: 0019 void initTestCase(void); 0020 void testValidAccountUri(void); 0021 void testInvalidAccountUri(void); 0022 void testInvalidCommandLine(void); 0023 }; 0024 0025 void CommandLineOptionsTest::initTestCase(void) 0026 { 0027 auto threadPool = QThreadPool::globalInstance(); 0028 QVERIFY2(threadPool, "should have a global thread pool by now"); 0029 threadPool->setMaxThreadCount(3); 0030 } 0031 0032 static bool prime(QCommandLineParser &parser, const QStringList &argv) 0033 { 0034 app::CommandLineOptions::addOptions(parser); 0035 return parser.parse(argv); 0036 } 0037 0038 void CommandLineOptionsTest::testValidAccountUri(void) 0039 { 0040 QCommandLineParser parser; 0041 model::AccountInput recipient; 0042 const auto argv = QStringList() 0043 << QStringLiteral("<dummy app>") 0044 << QStringLiteral("otpauth://hotp/issuer:valid?secret=VALUE&digits=8&period=60&issuer=issuer&counter=42&algorithm=sha512"); 0045 0046 app::CommandLineOptions uut(parser, prime(parser, argv)); 0047 QSignalSpy invalid(&uut, &app::CommandLineOptions::newAccountInvalid); 0048 QSignalSpy processed(&uut, &app::CommandLineOptions::newAccountProcessed); 0049 0050 QVERIFY2(uut.newAccountRequested(), "Account URI parsing should be requested"); 0051 QVERIFY2(uut.optionsOk(), "Commandline options should be marked as 'ok' (valid)"); 0052 QCOMPARE(uut.errorText(), QString()); 0053 0054 uut.handleNewAccount(&recipient); 0055 QVERIFY2(test::signal_eventually_emitted_once(processed), "Account URI should be processed by now"); 0056 QCOMPARE(invalid.count(), 0); 0057 0058 QCOMPARE(recipient.name(), QStringLiteral("valid")); 0059 QCOMPARE(recipient.issuer(), QStringLiteral("issuer")); 0060 QCOMPARE(recipient.counter(), QStringLiteral("42")); 0061 QCOMPARE(recipient.secret(), QStringLiteral("VALUE===")); 0062 QCOMPARE(recipient.tokenLength(), 8U); 0063 QCOMPARE(recipient.timeStep(), 60U); 0064 QCOMPARE(recipient.type(), model::AccountInput::TokenType::Hotp); 0065 QCOMPARE(recipient.algorithm(), model::AccountInput::TOTPAlgorithm::Sha512); 0066 0067 QVERIFY2(QThreadPool::globalInstance()->waitForDone(500), "the global thread pool should be done by now"); 0068 } 0069 0070 void CommandLineOptionsTest::testInvalidAccountUri(void) 0071 { 0072 QCommandLineParser parser; 0073 model::AccountInput recipient; 0074 const auto argv = QStringList() 0075 << QStringLiteral("<dummy app>") 0076 << QStringLiteral("not a valid otpauth:// URI"); 0077 0078 app::CommandLineOptions uut(parser, prime(parser, argv)); 0079 QSignalSpy invalid(&uut, &app::CommandLineOptions::newAccountInvalid); 0080 QSignalSpy processed(&uut, &app::CommandLineOptions::newAccountProcessed); 0081 0082 QVERIFY2(uut.newAccountRequested(), "Account URI parsing should be requested"); 0083 QVERIFY2(uut.optionsOk(), "Commandline options should be marked as 'ok' (valid)"); 0084 QCOMPARE(uut.errorText(), QString()); 0085 0086 uut.handleNewAccount(&recipient); 0087 QVERIFY2(test::signal_eventually_emitted_once(invalid), "Account URI should have been rejected by now"); 0088 QCOMPARE(processed.count(), 0); 0089 0090 QCOMPARE(recipient.name(), QString()); 0091 QCOMPARE(recipient.issuer(), QString()); 0092 QCOMPARE(recipient.counter(), QStringLiteral("0")); 0093 QCOMPARE(recipient.secret(), QString()); 0094 QCOMPARE(recipient.tokenLength(), 6U); 0095 QCOMPARE(recipient.timeStep(), 30U); 0096 QCOMPARE(recipient.type(), model::AccountInput::TokenType::Totp); 0097 QCOMPARE(recipient.algorithm(), model::AccountInput::TOTPAlgorithm::Sha1); 0098 0099 QVERIFY2(QThreadPool::globalInstance()->waitForDone(500), "the global thread pool should be done by now"); 0100 } 0101 0102 void CommandLineOptionsTest::testInvalidCommandLine(void) 0103 { 0104 QCommandLineParser parser; 0105 const auto argv = QStringList() 0106 << QStringLiteral("<dummy app>") 0107 << QStringLiteral("--invalid-option"); 0108 0109 app::CommandLineOptions uut(parser, prime(parser, argv)); 0110 QSignalSpy invalid(&uut, &app::CommandLineOptions::newAccountInvalid); 0111 QSignalSpy processed(&uut, &app::CommandLineOptions::newAccountProcessed); 0112 0113 QVERIFY2(!uut.optionsOk(), "Commandline options should not be marked as 'ok' (invalid)"); 0114 QVERIFY2(!uut.errorText().isEmpty(), "Commandline error message should not be empty"); 0115 QVERIFY2(!uut.newAccountRequested(), "Account URI parsing should not be requested"); 0116 0117 QCoreApplication::processEvents(QEventLoop::AllEvents, 500); 0118 QCOMPARE(processed.count(), 0); 0119 QCOMPARE(invalid.count(), 0); 0120 0121 QVERIFY2(QThreadPool::globalInstance()->waitForDone(500), "the global thread pool should be done by now"); 0122 } 0123 0124 QTEST_GUILESS_MAIN(CommandLineOptionsTest) 0125 0126 #include "commandline-options.moc"