File indexing completed on 2024-05-12 05:55:43

0001 /*
0002     This file is part of the Okteta Kasten Framework, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2012 Alex Richardson <alex.richardson@gmx.de>
0005     SPDX-FileCopyrightText: 2016 Aaron Bishop <erroneous@gmail.com>
0006 
0007     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0008 */
0009 
0010 #include "view/structures/parsers/parserutils.hpp"
0011 // Qt
0012 #include <QTest>
0013 #include <QScriptValue>
0014 #include <QScriptEngine>
0015 // Std
0016 #include <memory>
0017 #include <limits>
0018 
0019 class CommonParserTest : public QObject
0020 {
0021     Q_OBJECT
0022 
0023 private Q_SLOTS:
0024     void testIntFromString();
0025     void testIntFromString_data();
0026     void testUIntFromString();
0027     void testUIntFromString_data();
0028 
0029     void testIntFromScriptValue();
0030     void testIntFromScriptValue_data();
0031     void testUIntFromScriptValue();
0032     void testUIntFromScriptValue_data();
0033 
0034     void testToStringEncoding();
0035     void testToStringEncoding_data();
0036 };
0037 
0038 void CommonParserTest::testIntFromString_data()
0039 {
0040     QTest::addColumn<QString>("str");
0041     QTest::addColumn<bool>("okay");
0042     QTest::addColumn<int>("value");
0043 
0044     QTest::newRow("-1") << "-1" << true << -1;
0045     QTest::newRow("hex with minus") << "-0xff" << true << -0xff;
0046     QTest::newRow("0xff") << "0xff" << true << 0xff;
0047 
0048     int maxInt = 0x7fffffff;
0049     QTEST_ASSERT(maxInt == std::numeric_limits<int>::max());
0050     QTest::newRow("max decimal") << "2147483647" << true << maxInt;
0051     QTest::newRow("max hex") << "0x7fffffff" << true << maxInt;
0052     QTest::newRow("max hex no leading 0x") << "7fffffff" << false;
0053 
0054     QTest::newRow("max+1 decimal") << "2147483648" << false;
0055     QTest::newRow("max+1 hex") << "0x80000000" << false;
0056     QTest::newRow("max-1 decimal") << "2147483646" << true << 0x7ffffffe;
0057     QTest::newRow("max-1 hex") << "7ffffffe" << false << 2147483646;
0058 
0059     int minInt = -0x80000000;
0060     QTEST_ASSERT(minInt == std::numeric_limits<int>::min());
0061     QTest::newRow("min decimal") << "-2147483648" << true << minInt;
0062     QTest::newRow("min hex") << "-0x80000000" << true << minInt;
0063 
0064     QTest::newRow("min+1 decimal") << "-2147483647" << true << -0x7fffffff;
0065     QTest::newRow("min+1 hex") << "-0x7fffffff" << true << -2147483647;
0066     QTest::newRow("min-1 decimal") << "-2147483649" << false;
0067     QTest::newRow("min-1 hex") << "-0x80000001" << false;
0068 
0069 }
0070 
0071 void CommonParserTest::testIntFromString()
0072 {
0073     QFETCH(QString, str);
0074     QFETCH(bool, okay);
0075 
0076     ParsedNumber<int> result = ParserUtils::intFromString(str);
0077     QCOMPARE(result.string, str);
0078     QCOMPARE(result.isValid, okay);
0079     if (result.isValid) {
0080         QFETCH(int, value);
0081         QCOMPARE(result.value, value);
0082     }
0083 }
0084 
0085 void CommonParserTest::testUIntFromString_data()
0086 {
0087     QTest::addColumn<QString>("str");
0088     QTest::addColumn<bool>("okay");
0089     QTest::addColumn<uint>("value");
0090 
0091     QTest::newRow("-1") << "-1" << false;
0092     QTest::newRow("0xff") << "0xff" << true << 0xffU;
0093     QTest::newRow("1234") << "1234" << true << 1234U;
0094 
0095     uint maxUint = 0xffffffff;
0096     QTEST_ASSERT(maxUint == std::numeric_limits<uint>::max());
0097     QTest::newRow("max decimal") << "4294967295" << true << maxUint;
0098     QTest::newRow("max hex") << "0xffffffff" << true << maxUint;
0099     QTest::newRow("max hex no leading 0x") << "ffffffff" << false;
0100 
0101     QTest::newRow("max+1 decimal") << "4294967296" << false;
0102     QTest::newRow("max+1 hex") << "0x100000000" << false;
0103 
0104 }
0105 
0106 void CommonParserTest::testUIntFromString()
0107 {
0108     QFETCH(QString, str);
0109     QFETCH(bool, okay);
0110 
0111     ParsedNumber<uint> result = ParserUtils::uintFromString(str);
0112     QCOMPARE(result.string, str);
0113     QCOMPARE(result.isValid, okay);
0114     if (result.isValid) {
0115         QFETCH(uint, value);
0116         QCOMPARE(result.value, value);
0117     }
0118 }
0119 
0120 void CommonParserTest::testIntFromScriptValue_data()
0121 {
0122     QTest::addColumn<QScriptValue>("scriptValue");
0123     QTest::addColumn<bool>("okay");
0124     QTest::addColumn<int>("value");
0125 
0126     auto* engine = new QScriptEngine(this);
0127     QTest::newRow("invalid script value") << QScriptValue() << false;
0128     QTest::newRow("boolean true") << QScriptValue(true) << false;
0129     QTest::newRow("boolean false") << QScriptValue(false) << false;
0130     QTest::newRow("null script value") << engine->nullValue() << false;
0131     QTest::newRow("undefined script value") << engine->undefinedValue() << false;
0132     QTest::newRow("array") << engine->newArray(5) << false;
0133     QTest::newRow("object") << engine->newObject() << false;
0134     QTest::newRow("float") << QScriptValue(1234.5) << false;
0135 
0136     QTest::newRow("-1234 number") << QScriptValue(-1234) << true << -1234;
0137     QTest::newRow("-1234 string") << QScriptValue(QStringLiteral("-1234")) << true << -1234;
0138     QTest::newRow("1234 number") << QScriptValue(1234) << true << 1234;
0139     QTest::newRow("1234 string") << QScriptValue(QStringLiteral("1234")) << true << 1234;
0140     QTest::newRow("0xff number") << QScriptValue(0xff) << true << 0xff;
0141     QTest::newRow("0xff string") << QScriptValue(QStringLiteral("0xff")) << true << 0xff;
0142     QTest::newRow("-0xff number") << QScriptValue(-0xff) << true << -0xff;
0143     QTest::newRow("-0xff string") << QScriptValue(QStringLiteral("-0xff")) << true << -0xff;
0144 
0145     int maxInt = 0x7fffffff;
0146     QTEST_ASSERT(maxInt == std::numeric_limits<int>::max());
0147     QTest::newRow("max int") << QScriptValue(maxInt) << true << maxInt;
0148     QTest::newRow("max double") << QScriptValue(double(maxInt)) << true << maxInt;
0149     QTest::newRow("max string") << QScriptValue(QStringLiteral("2147483647")) << true << maxInt;
0150     QTest::newRow("max hex string") << QScriptValue(QStringLiteral("0x7fffffff")) << true << maxInt;
0151     // to int32 wraps around
0152     QTest::newRow("max+1") << QScriptValue(double(maxInt) + 1) << false;
0153     QTest::newRow("max+1 string") << QScriptValue(QStringLiteral("2147483648")) << false;
0154     QTest::newRow("max+1 hex string") << QScriptValue(QStringLiteral("0x80000000")) << false;
0155     QTest::newRow("max+2") << QScriptValue(double(maxInt) + 2) << false;
0156 
0157     int minInt = -0x80000000;
0158     QTEST_ASSERT(minInt == std::numeric_limits<int>::min());
0159     QTest::newRow("min int") << QScriptValue(minInt) << true << minInt;
0160     QTest::newRow("min double") << QScriptValue(double(minInt)) << true << minInt;
0161     QTest::newRow("min string") << QScriptValue(QStringLiteral("-2147483648")) << true << minInt;
0162     QTest::newRow("min hex string") << QScriptValue(QStringLiteral("-0x80000000")) << true << minInt;
0163     QTest::newRow("min-1") << QScriptValue(double(minInt) - 1) << false;
0164     QTest::newRow("large number") << QScriptValue(double(0x123456789a)) << false;
0165 
0166 }
0167 
0168 void CommonParserTest::testIntFromScriptValue()
0169 {
0170     QFETCH(QScriptValue, scriptValue);
0171     QFETCH(bool, okay);
0172 
0173     ParsedNumber<int> result = ParserUtils::intFromScriptValue(scriptValue);
0174     QCOMPARE(result.string, scriptValue.toString());
0175     if (result.isValid != okay) {
0176         qDebug() << scriptValue.toString() << ", int =" << scriptValue.toInt32() << ", double = "
0177                  << scriptValue.toNumber();
0178     }
0179     QCOMPARE(result.isValid, okay);
0180     if (result.isValid) {
0181         QFETCH(int, value);
0182         QCOMPARE(result.value, value);
0183     }
0184 }
0185 
0186 void CommonParserTest::testUIntFromScriptValue_data()
0187 {
0188     QTest::addColumn<QScriptValue>("scriptValue");
0189     QTest::addColumn<bool>("okay");
0190     QTest::addColumn<uint>("value");
0191 
0192     auto* engine = new QScriptEngine(this);
0193     QTest::newRow("invalid script value") << QScriptValue() << false;
0194     QTest::newRow("boolean true") << QScriptValue(true) << false;
0195     QTest::newRow("boolean false") << QScriptValue(false) << false;
0196     QTest::newRow("null script value") << engine->nullValue() << false;
0197     QTest::newRow("undefined script value") << engine->undefinedValue() << false;
0198     QTest::newRow("array") << engine->newArray(5) << false;
0199     QTest::newRow("object") << engine->newObject() << false;
0200     QTest::newRow("float") << QScriptValue(1234.5) << false;
0201 
0202     QTest::newRow("1234 number") << QScriptValue(1234) << true << 1234U;
0203     QTest::newRow("1234 string") << QScriptValue(QStringLiteral("1234")) << true << 1234U;
0204     QTest::newRow("0xff number") << QScriptValue(0xff) << true << 0xffU;
0205     QTest::newRow("0xff string") << QScriptValue(QStringLiteral("0xff")) << true << 0xffU;
0206 
0207     QTest::newRow("negative string") << QScriptValue(QStringLiteral("-1")) << false;
0208     QTest::newRow("negative number") << QScriptValue(-1) << false;
0209 
0210     uint maxInt = 0xffffffff;
0211     QTEST_ASSERT(maxInt == std::numeric_limits<uint>::max());
0212     QTest::newRow("max") << QScriptValue(double(maxInt)) << true << maxInt;
0213     QTest::newRow("max int") << QScriptValue(maxInt) << true << maxInt;
0214     QTest::newRow("max string") << QScriptValue(QStringLiteral("4294967295")) << true << maxInt;
0215     QTest::newRow("max hex string") << QScriptValue(QStringLiteral("0xffffffff")) << true << maxInt;
0216     QTest::newRow("max+1") << QScriptValue(double(maxInt) + 1) << false;
0217     QTest::newRow("max+1 string") << QScriptValue(QStringLiteral("4294967296")) << false;
0218     QTest::newRow("max+1 hex string") << QScriptValue(QStringLiteral("0x100000000")) << false;
0219     QTest::newRow("large number") << QScriptValue(double(0x123456789a)) << false;
0220 }
0221 
0222 void CommonParserTest::testUIntFromScriptValue()
0223 {
0224     QFETCH(QScriptValue, scriptValue);
0225     QFETCH(bool, okay);
0226 
0227     ParsedNumber<uint> result = ParserUtils::uintFromScriptValue(scriptValue);
0228     QCOMPARE(result.string, scriptValue.toString());
0229     if (result.isValid != okay) {
0230         qDebug() << scriptValue.toString() << ", uint =" << scriptValue.toUInt32() << ", double = "
0231                  << scriptValue.toNumber();
0232     }
0233     QCOMPARE(result.isValid, okay);
0234     if (result.isValid) {
0235         QFETCH(uint, value);
0236         QCOMPARE(result.value, value);
0237     }
0238 }
0239 
0240 inline void CommonParserTest::testToStringEncoding()
0241 {
0242     QFETCH(QString, str);
0243     QFETCH(int, expected);
0244     std::unique_ptr<ScriptLogger> logger(new ScriptLogger());
0245     StringDataInformation::StringType type =
0246         ParserUtils::toStringEncoding(str, LoggerWithContext(logger.get(), QString()));
0247     QCOMPARE((int)type, expected);
0248 }
0249 
0250 inline void CommonParserTest::testToStringEncoding_data()
0251 {
0252     QTest::addColumn<QString>("str");
0253     QTest::addColumn<int>("expected");
0254 
0255     QTest::newRow("ascii") << "ascii" << (int)StringDataInformation::StringType::ASCII;
0256     QTest::newRow("ebcdic") << "ebcdic" << (int)StringDataInformation::StringType::EBCDIC;
0257     QTest::newRow("ascii upper") << "ASCII" << (int)StringDataInformation::StringType::ASCII;
0258     QTest::newRow("excess char") << "asciii" << (int)StringDataInformation::StringType::InvalidEncoding;
0259 
0260     QTest::newRow("latin1") << "latin1" << (int)StringDataInformation::StringType::Latin1;
0261     QTest::newRow("latin-1") << "latin-1" << (int)StringDataInformation::StringType::Latin1;
0262     QTest::newRow("latin") << "latin" << (int)StringDataInformation::StringType::InvalidEncoding;
0263 
0264     QTest::newRow("utf8") << "utf8" << (int)StringDataInformation::StringType::UTF8;
0265     QTest::newRow("utf-8") << "utf-8" << (int)StringDataInformation::StringType::UTF8;
0266     QTest::newRow("utf--8") << "utf--8" << (int)StringDataInformation::StringType::InvalidEncoding;
0267 
0268     QTest::newRow("utf16") << "utf16" << (int)StringDataInformation::StringType::UTF16_LE;
0269     QTest::newRow("utf-16") << "utf-16" << (int)StringDataInformation::StringType::UTF16_LE;
0270     QTest::newRow("utf-16le") << "utf-16le" << (int)StringDataInformation::StringType::UTF16_LE;
0271     QTest::newRow("utf-16-le") << "utf-16-le" << (int)StringDataInformation::StringType::UTF16_LE;
0272     QTest::newRow("utf-16--le") << "utf-16--le" << (int)StringDataInformation::StringType::InvalidEncoding;
0273 
0274     QTest::newRow("utf-16be") << "utf-16be" << (int)StringDataInformation::StringType::UTF16_BE;
0275     QTest::newRow("utf-16-be") << "utf-16-be" << (int)StringDataInformation::StringType::UTF16_BE;
0276     QTest::newRow("utf-16-abe") << "utf-16-abe" << (int)StringDataInformation::StringType::InvalidEncoding;
0277 
0278     QTest::newRow("utf32") << "utf32" << (int)StringDataInformation::StringType::UTF32_LE;
0279     QTest::newRow("utf-32") << "utf-32" << (int)StringDataInformation::StringType::UTF32_LE;
0280     QTest::newRow("utf-32le") << "utf-32le" << (int)StringDataInformation::StringType::UTF32_LE;
0281     QTest::newRow("utf-32-le") << "utf-32-le" << (int)StringDataInformation::StringType::UTF32_LE;
0282     QTest::newRow("utf-32--le") << "utf-32--le" << (int)StringDataInformation::StringType::InvalidEncoding;
0283 
0284     QTest::newRow("utf-32be") << "utf-32be" << (int)StringDataInformation::StringType::UTF32_BE;
0285     QTest::newRow("utf-32-be") << "utf-32-be" << (int)StringDataInformation::StringType::UTF32_BE;
0286     QTest::newRow("utf-32-abe") << "utf-32-abe" << (int)StringDataInformation::StringType::InvalidEncoding;
0287 }
0288 
0289 QTEST_GUILESS_MAIN(CommonParserTest)
0290 
0291 #include "commonparsertest.moc"