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 "base32/base32.h"
0006 
0007 #include <QTest>
0008 #include <QtDebug>
0009 
0010 class Base32CodingDecodingTest: public QObject
0011 {
0012     Q_OBJECT
0013 private Q_SLOTS:
0014     void testSample(void);
0015     void testSample_data(void);
0016 };
0017 
0018 static int lastPadBits(int data)
0019 {
0020     switch (data) {
0021     case 7:
0022         return 3;
0023     case 5:
0024         return 1;
0025     case 4:
0026         return 4;
0027     case 2:
0028         return 2;
0029     default:
0030         return 0;
0031     }
0032 }
0033 
0034 static int outputSize(int data)
0035 {
0036     switch (data) {
0037     case 8:
0038         return 5;
0039     case 7:
0040         return 4;
0041     case 5:
0042         return 3;
0043     case 4:
0044         return 2;
0045     case 2:
0046         return 1;
0047     default:
0048         return 0;
0049     }
0050 }
0051 
0052 static void define_test_data(void)
0053 {
0054     QTest::addColumn<QString>("input");
0055     QTest::addColumn<QByteArray>("expected");
0056 }
0057 
0058 static void define_test_case(const QString &input, int len, char value)
0059 {
0060     static const QString testCase(QLatin1String("size: %1: '%2' ... 0x%3"));
0061     QByteArray expected;
0062     int outputSz = outputSize(len);
0063     expected.reserve(outputSz);
0064     expected.resize(outputSz);
0065     expected.fill('\x0');
0066     if (len > 0) {
0067         expected[expected.size() - 1] = value;
0068     }
0069 
0070     QTest::newRow(qPrintable(testCase.arg(len).arg(input).arg(QLatin1String(expected.toHex())))) << input << expected;
0071 }
0072 
0073 static inline QChar pick(int v)
0074 {
0075     return v < 26 ? QLatin1Char('A' + v) : QLatin1Char('2' + v - 26);
0076 }
0077 
0078 static void define_test_case(int len)
0079 {
0080     QString prefix;
0081     QByteArray output;
0082     int padBits = lastPadBits(len);
0083     for(int i = 3; i < len; ++i) {
0084         prefix += QLatin1Char('A');
0085     }
0086 
0087     for (int b = 0; b < 256; ++b) {
0088         int i1 = ((b << padBits) >> 10) & 0x1F;
0089         int i2 = (b >> (5 - padBits)) & 0x1F;
0090         int i3 = (b << padBits) & 0x1F;
0091 
0092         QString input = prefix;
0093         if (len >= 3) {
0094             input += pick(i1);
0095         }
0096         input += pick(i2);
0097         input += pick(i3);
0098 
0099         while(input.size() < 8) {
0100             input += QLatin1Char('=');
0101         }
0102         define_test_case(input, len, b);
0103     }
0104 }
0105 
0106 void Base32CodingDecodingTest::testSample(void)
0107 {
0108     QFETCH(QString, input);
0109     QFETCH(QByteArray, expected);
0110 
0111     QByteArray work(expected.size(), '\x0');
0112 
0113     QCOMPARE(base32::decode(input, work.data(), work.size()), std::optional<size_t>(expected.size()));
0114     QCOMPARE(work, expected);
0115 }
0116 
0117 void Base32CodingDecodingTest::testSample_data(void)
0118 {
0119     define_test_data();
0120     QTest::newRow(qPrintable(QLatin1String("the empty string"))) << QString(QLatin1String("")) << QByteArray();
0121     define_test_case(2);
0122     define_test_case(4);
0123     define_test_case(5);
0124     define_test_case(7);
0125     define_test_case(8);
0126 }
0127 
0128 QTEST_APPLESS_MAIN(Base32CodingDecodingTest)
0129 
0130 #include "base32-coding-decoding.moc"