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 "oath/oath.h"
0006 
0007 #include <QTest>
0008 #include <QtDebug>
0009 
0010 class TimeStepCounterTest: public QObject
0011 {
0012     Q_OBJECT
0013 private Q_SLOTS:
0014     void invalidCount(void);
0015     void invalidCount_data(void);
0016     void validCount(void);
0017     void validCount_data(void);
0018     void rfcTestVector(void);
0019     void rfcTestVector_data(void);
0020 };
0021 
0022 static void define_valid_test_case(const QDateTime &epoch, qint64 now, uint timeStep, quint64 expected)
0023 {
0024     static const QString testCase(QLatin1String("%2 - %1 (%3) ... %4"));
0025     QTest::newRow(qPrintable(testCase.arg(epoch.toMSecsSinceEpoch()).arg(now).arg(timeStep).arg(expected))) << epoch << now << timeStep << expected;
0026 }
0027 
0028 static void define_invalid_test_case(const QDateTime &epoch, qint64 now, uint timeStep)
0029 {
0030     static const QString testCase(QLatin1String("%2 - %1 (%3)"));
0031     QTest::newRow(qPrintable(testCase.arg(epoch.toMSecsSinceEpoch()).arg(now).arg(timeStep))) << epoch << now << timeStep;
0032 }
0033 
0034 void TimeStepCounterTest::validCount(void)
0035 {
0036     QFETCH(QDateTime, epoch);
0037     QFETCH(qint64, now);
0038     QFETCH(uint, timeStep);
0039     QFETCH(quint64, expected);
0040     const std::function<qint64(void)> clock([now](void) -> qint64
0041     {
0042         return now;
0043     });
0044     QCOMPARE(oath::count(epoch, timeStep, clock), std::optional<quint64>(expected));
0045 }
0046 
0047 void TimeStepCounterTest::validCount_data(void)
0048 {
0049     QTest::addColumn<QDateTime>("epoch");
0050     QTest::addColumn<qint64>("now");
0051     QTest::addColumn<uint>("timeStep");
0052     QTest::addColumn<quint64>("expected");
0053 
0054     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1500LL, 30UL, 0ULL);
0055     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1500LL, 1UL, 1ULL);
0056     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 30500LL, 30UL, 1ULL);
0057 }
0058 
0059 void TimeStepCounterTest::invalidCount(void)
0060 {
0061     QFETCH(QDateTime, epoch);
0062     QFETCH(qint64, now);
0063     QFETCH(uint, timeStep);
0064     const std::function<qint64(void)> clock([now](void) -> qint64
0065     {
0066         return now;
0067     });
0068     QVERIFY2(!oath::count(epoch, timeStep, clock), "counting timesteps should fail (invalid inputs)");
0069 }
0070 
0071 void TimeStepCounterTest::invalidCount_data(void)
0072 {
0073     QTest::addColumn<QDateTime>("epoch");
0074     QTest::addColumn<qint64>("now");
0075     QTest::addColumn<uint>("timeStep");
0076     QTest::addColumn<quint64>("expected");
0077 
0078     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(1500LL), 0LL, 30UL);
0079     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1500LL, 0UL);
0080 }
0081 
0082 static void define_rfc_test_case(const QString &datetime, quint64 expected)
0083 {
0084     static QString testCase(QLatin1String("%1 ... 0x%2"));
0085     const QDateTime dt = QDateTime::fromString(datetime, Qt::ISODate);
0086     QTest::newRow(qPrintable(testCase.arg(datetime).arg(expected, 8, 16, QLatin1Char('0')))) << dt << expected;
0087 }
0088 
0089 /*
0090  * (Static) test vector params obtained from RFC-6238
0091  * https://tools.ietf.org/html/rfc6238#page-9
0092  */
0093 
0094 void TimeStepCounterTest::rfcTestVector(void)
0095 {
0096     QFETCH(QDateTime, now);
0097     const QDateTime epoch = QDateTime::fromMSecsSinceEpoch(0);
0098     const uint timeStep = 30U;
0099 
0100     std::optional<quint64> counter = oath::count(epoch, timeStep, [now](void) -> qint64
0101     {
0102         return now.toMSecsSinceEpoch();
0103     });
0104 
0105     QVERIFY2(counter, "should be able to count timesteps using the settings of the RFC test vector");
0106     QTEST(*counter, "rfc-test-vector");
0107 }
0108 
0109 void TimeStepCounterTest::rfcTestVector_data(void)
0110 {
0111     QTest::addColumn<QDateTime>("now");
0112     QTest::addColumn<quint64>("rfc-test-vector");
0113 
0114     define_rfc_test_case(QStringLiteral("1970-01-01 00:00:59Z"), 0x1ULL);
0115     define_rfc_test_case(QStringLiteral("2005-03-18 01:58:29Z"), 0x23523ECULL);
0116     define_rfc_test_case(QStringLiteral("2005-03-18 01:58:31Z"), 0x23523EDULL);
0117     define_rfc_test_case(QStringLiteral("2009-02-13 23:31:30Z"), 0x273EF07ULL);
0118     define_rfc_test_case(QStringLiteral("2033-05-18 03:33:20Z"), 0x3F940AAULL);
0119     define_rfc_test_case(QStringLiteral("2603-10-11 11:33:20Z"), 0x27BC86AAULL);
0120 }
0121 
0122 QTEST_APPLESS_MAIN(TimeStepCounterTest)
0123 
0124 #include "count-timesteps.moc"