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

0001 /*
0002  * SPDX-License-Identifier: GPL-3.0-or-later
0003  * SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
0004  */
0005 #include "oath/oath.h"
0006 
0007 #include <QTest>
0008 #include <QtDebug>
0009 
0010 #include <limits>
0011 
0012 class TimeStepCountConversionTest: public QObject // clazy:exclude=ctor-missing-parent-argument
0013 {
0014     Q_OBJECT
0015 private Q_SLOTS:
0016     void invalidCount(void);
0017     void invalidCount_data(void);
0018     void validCount(void);
0019     void validCount_data(void);
0020 };
0021 
0022 
0023 static void define_valid_test_case(const QDateTime &epoch, uint timeStep, quint64 count, const QDateTime &expected)
0024 {
0025     static const QString testCase(QStringLiteral("%1 + %2 * 1000 * %3 ... %4"));
0026     QTest::newRow(qPrintable(testCase.arg(epoch.toMSecsSinceEpoch()).arg(timeStep).arg(count).arg(expected.toMSecsSinceEpoch()))) << epoch << timeStep << count << expected;
0027 }
0028 
0029 static void define_invalid_test_case(const QDateTime &epoch, uint timeStep, quint64 count)
0030 {
0031     static const QString testCase(QStringLiteral("%1 + %2 * 1000 * %3"));
0032     QTest::newRow(qPrintable(testCase.arg(epoch.toMSecsSinceEpoch()).arg(timeStep).arg(count))) << epoch << timeStep << count;
0033 }
0034 
0035 void TimeStepCountConversionTest::validCount(void)
0036 {
0037     QFETCH(QDateTime, epoch);
0038     QFETCH(uint, timeStep);
0039     QFETCH(quint64, count);
0040 
0041     auto result = oath::fromCounter(count, epoch, timeStep);
0042     QVERIFY2(result, "should be able to determine the datetime associated with the counter");
0043     QTEST(*result, "expected");
0044 }
0045 
0046 void TimeStepCountConversionTest::validCount_data(void)
0047 {
0048     QTest::addColumn<QDateTime>("epoch");
0049     QTest::addColumn<uint>("timeStep");
0050     QTest::addColumn<quint64>("count");
0051     QTest::addColumn<QDateTime>("expected");
0052 
0053     const qint64 min = std::numeric_limits<qint64>::min();
0054     const qint64 s2038 = std::numeric_limits<qint32>::max();
0055 
0056     // few basic cases
0057     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 30UL, 0ULL, QDateTime::fromMSecsSinceEpoch(0LL));
0058     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 30UL, 1ULL, QDateTime::fromMSecsSinceEpoch(30'000LL));
0059     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(-30'000LL), 30UL, 1ULL, QDateTime::fromMSecsSinceEpoch(0LL));
0060 
0061     // checking max 'classic' 32bit unix time for counting utc seconds
0062     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 30UL, s2038/ 30LL, QDateTime::fromMSecsSinceEpoch(30'000LL * (s2038 / 30LL)));
0063     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1UL, s2038, QDateTime::fromMSecsSinceEpoch(1'000LL * s2038));
0064 
0065     // finding the actual upper limit(s) which QDateTime can cope with
0066     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1ULL, 0x7fffffffff921fd8ULL / 1000ULL, QDateTime::fromMSecsSinceEpoch(0x7fffffffff921fd8LL));
0067     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(808LL), 1ULL, 0x7fffffffff921fd8ULL / 1000ULL - 1ULL, QDateTime::fromMSecsSinceEpoch(0x7fffffffff921fd8LL - 192LL));
0068     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(807LL), 1ULL, 0x7fffffffff921fd8ULL / 1000ULL, QDateTime::fromMSecsSinceEpoch(0x7fffffffff921fd8LL + 807LL));
0069 
0070     // finding the lower limit(s) which QDateTime can cope with
0071     define_valid_test_case(QDateTime::fromMSecsSinceEpoch(min), 1UL, 0ULL, QDateTime::fromMSecsSinceEpoch(min));
0072 }
0073 
0074 void TimeStepCountConversionTest::invalidCount(void)
0075 {
0076     QFETCH(QDateTime, epoch);
0077     QFETCH(uint, timeStep);
0078     QFETCH(quint64, count);
0079 
0080     QVERIFY2(!oath::fromCounter(count, epoch, timeStep), "should not be able to associate a datetime with the counter");
0081 }
0082 
0083 void TimeStepCountConversionTest::invalidCount_data(void)
0084 {
0085     QTest::addColumn<QDateTime>("epoch");
0086     QTest::addColumn<uint>("timeStep");
0087     QTest::addColumn<quint64>("count");
0088 
0089     const quint64 max = std::numeric_limits<quint64>::max();
0090 
0091     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1UL, max / 2);
0092     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1UL, max);
0093     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(std::numeric_limits<qint64>::min()), 1UL, max);
0094     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(std::numeric_limits<qint64>::min()), 1UL, max / 1000ULL + 1ULL);
0095 
0096     // fits within qint64 ultimately but QDateTime gets confused about it
0097     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1ULL, (quint64) (max / 1000LL));
0098     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1ULL, (quint64) (max >> 9));
0099     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(0LL), 1ULL, (quint64) (max >> 10) + (max >> 11L));
0100     define_invalid_test_case(QDateTime::fromMSecsSinceEpoch(808LL), 1ULL, 0x7fffffffffffffffULL / 1000ULL);
0101 }
0102 
0103 QTEST_APPLESS_MAIN(TimeStepCountConversionTest)
0104 
0105 #include "convert-timestep-counter.moc"