File indexing completed on 2024-04-28 05:50:04

0001 /*
0002  * SPDX-License-Identifier: GPL-3.0-or-later
0003  * SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
0004  */
0005 #include "model/qr.h"
0006 #include "model/input.h"
0007 
0008 #include <QTest>
0009 
0010 class QrInputTest: public QObject // clazy:exclude=ctor-missing-parent-argument
0011 {
0012     Q_OBJECT
0013 private Q_SLOTS:
0014     void testValidUri(void);
0015     void testValidUri_data(void);
0016     void testInvalidUri(void);
0017     void testInvalidUri_data(void);
0018 };
0019 
0020 
0021 static void define_valid_test_case(const char *testCase, const QString &uri, const QString &name,
0022                                    const QString &issuer, const QString &secret, const QString &counter,
0023                                    uint tokenLength, uint timeStep, model::AccountInput::TokenType type,
0024                                    model::AccountInput::TOTPAlgorithm algorithm)
0025 {
0026     QTest::newRow(testCase) << uri << name << issuer << secret << counter << tokenLength << timeStep << type
0027         << algorithm;
0028 }
0029 
0030 static void define_invalid_test_case(const char *testCase, const QString &uri)
0031 {
0032     QTest::newRow(testCase) << uri;
0033 }
0034 
0035 void QrInputTest::testValidUri(void)
0036 {
0037     QFETCH(QString, uri);
0038 
0039     model::AccountInput target;
0040 
0041     auto result = model::QrParameters::parse(uri);
0042     QVERIFY2(result, "should be able to parse valid URIs");
0043 
0044     result->populate(&target);
0045 
0046     QTEST(target.name(), "name");
0047     QTEST(target.issuer(), "issuer");
0048     QTEST(target.secret(), "secret");
0049     QTEST(target.counter(), "counter");
0050     QTEST(target.tokenLength(), "tokenLength");
0051     QTEST(target.timeStep(), "timeStep");
0052     QTEST(target.type(), "type");
0053     QTEST(target.algorithm(), "algorithm");
0054 }
0055 
0056 void QrInputTest::testValidUri_data(void)
0057 {
0058     QTest::addColumn<QString>("uri");
0059     QTest::addColumn<QString>("name");
0060     QTest::addColumn<QString>("issuer");
0061     QTest::addColumn<QString>("secret");
0062     QTest::addColumn<QString>("counter");
0063     QTest::addColumn<uint>("tokenLength");
0064     QTest::addColumn<uint>("timeStep");
0065     QTest::addColumn<model::AccountInput::TokenType>("type");
0066     QTest::addColumn<model::AccountInput::TOTPAlgorithm>("algorithm");
0067 
0068     define_valid_test_case("hotp (all fields set)",
0069         QStringLiteral("otpauth://hotp/issuer:valid?secret=VALUE&digits=8&period=60&issuer=issuer&counter=42&algorithm=sha512"),
0070         QStringLiteral("valid"), QStringLiteral("issuer"), QStringLiteral("VALUE==="), QStringLiteral("42"), 8U, 60U,
0071         model::AccountInput::TokenType::Hotp, model::AccountInput::TOTPAlgorithm::Sha512
0072     );
0073 }
0074 
0075 void QrInputTest::testInvalidUri(void)
0076 {
0077     QFETCH(QString, uri);
0078     QVERIFY2(!model::QrParameters::parse(uri), "should reject invalid URIs");
0079 }
0080 
0081 void QrInputTest::testInvalidUri_data(void)
0082 {
0083     QTest::addColumn<QString>("uri");
0084 
0085     define_invalid_test_case("token length not a number", QStringLiteral("otpauth://totp/invalid?secret=VALUE&digits=nan"));
0086     define_invalid_test_case("token length too small", QStringLiteral("otpauth://totp/invalid?secret=VALUE&digits=2"));
0087     define_invalid_test_case("token length too large", QStringLiteral("otpauth://totp/invalid?secret=VALUE&digits=22"));
0088 
0089     define_invalid_test_case("time step not a number", QStringLiteral("otpauth://totp/invalid?secret=VALUE&period=nan"));
0090     define_invalid_test_case("time step too small", QStringLiteral("otpauth://totp/invalid?secret=VALUE&period=0"));
0091     define_invalid_test_case("time step too large", QStringLiteral("otpauth://totp/invalid?secret=VALUE&period=999999999999"));
0092 
0093     define_invalid_test_case("invalid base32 secret", QStringLiteral("otpauth://totp/invalid?secret=19"));
0094     define_invalid_test_case("empty secret", QStringLiteral("otpauth://totp/invalid?secret="));
0095 
0096     define_invalid_test_case("counter not a number", QStringLiteral("otpauth://hotp/invalid?secret=VALUE&counter=nan"));
0097 
0098     define_invalid_test_case("invalid algorithm ", QStringLiteral("otpauth://totp/invalid?secret=VALUE&algorithm=foo"));
0099 
0100     define_invalid_test_case("name contains non-printable characters", QStringLiteral("otpauth://totp/inv%00alid?secret=VALUE"));
0101 
0102     define_invalid_test_case("issuer contains non-printable characters", QStringLiteral("otpauth://totp/iss%00:invalid?secret=VALUE"));
0103     define_invalid_test_case("issuer parameter contains non-printable characters", QStringLiteral("otpauth://totp/invalid?secret=VALUE&issuer=iss%03"));
0104 }
0105 
0106 QTEST_APPLESS_MAIN(QrInputTest)
0107 
0108 #include "qr-input.moc"