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

0001 /*
0002  *    This file is part of the Okteta Kasten module, made within the KDE community.
0003  *
0004  *    SPDX-FileCopyrightText: 2012 Alex Richardson <alex.richardson@gmx.de>
0005  *
0006  *    SPDX-License-Identifier: LGPL-2.1-or-later
0007  */
0008 
0009 #include "view/structures/datatypes/primitive/primitivetemplateinfo.hpp"
0010 #include "view/structures/datatypes/primitive/primitivedatainformation.hpp"
0011 #include "view/structures/datatypes/primitive/bitfield/signedbitfielddatainformation.hpp"
0012 #include "view/structures/datatypes/primitive/bitfield/unsignedbitfielddatainformation.hpp"
0013 #include "view/structures/datatypes/primitive/bitfield/boolbitfielddatainformation.hpp"
0014 #include "view/structures/datatypes/primitivefactory.hpp"
0015 #include "structureviewpreferences.hpp"
0016 // Okteta
0017 #include <Okteta/ByteArrayModel>
0018 // KF
0019 #include <KLocalizedString>
0020 // Qt
0021 #include <QTest>
0022 #include <QtGlobal>
0023 #include <QLocale>
0024 // Std
0025 #include <memory>
0026 #include <limits>
0027 
0028 inline uint qHash(PrimitiveDataType type)
0029 {
0030     return ::qHash(static_cast<int>(type));
0031 }
0032 
0033 class PrimitiveDataInformationTest : public QObject
0034 {
0035     Q_OBJECT
0036 
0037 private:
0038     template <typename s, typename u>
0039     void addRowsGetAndSetSigned(PrimitiveDataType type, const char* name);
0040     template <typename T>
0041     void addRowsGetAndSetUnsigned(PrimitiveDataType type, const char* name);
0042     void checkSignedDisplayBase(int expected);
0043     void checkUnsignedDisplayBase(int expected);
0044     int minimumSignedBits(qint64 value); // get the least number of bits this can be represented in
0045     int minimumUnsignedBits(quint64 value); // get the least number of bits this can be represented in
0046 
0047 private Q_SLOTS:
0048     void initTestCase();
0049     void testValueStringFloat();
0050     void testValueStringDouble();
0051     void testValueStringChar();
0052     void testValueStringInt();
0053     void testValueStringInt_data();
0054     void testValueStringUIntAndBool();
0055     void testValueStringUIntAndBool_data();
0056     void testToAndFromVariant();
0057     void testGetAndSetValue();
0058     void testGetAndSetValue_data();
0059     void testFromVariant();
0060     void cleanupTestCase();
0061 
0062 private:
0063     QHash<PrimitiveDataType, PrimitiveDataInformation*> basic;
0064     SignedBitfieldDataInformation* signedBitfield;
0065     UnsignedBitfieldDataInformation* unsignedBitfield;
0066     BoolBitfieldDataInformation* boolBitfield;
0067     // TODO enum
0068 //     Okteta::Byte* data;
0069 //     std::unique_ptr<Okteta::ByteArrayModel> model;
0070 };
0071 
0072 Q_DECLARE_METATYPE(PrimitiveDataInformation*)
0073 Q_DECLARE_METATYPE(AllPrimitiveTypes)
0074 
0075 int PrimitiveDataInformationTest::minimumSignedBits(qint64 value)
0076 {
0077     if (value == 0) {
0078         return 1;
0079     }
0080     if (value >= 0) {
0081         return minimumUnsignedBits(quint64(value)) + 1;
0082     }
0083     if (value == -1) { // has no zero in it -> can't determine size
0084         return 1;
0085     }
0086     // find the first zero
0087     for (int i = 63; i >= 0; --i) {
0088         if ((value & (qint64(1) << i)) == 0) {
0089             return i + 2; // found first zero, we need one bit more
0090         }
0091     }
0092 
0093     QTEST_ASSERT(false);
0094     return 65;
0095 }
0096 
0097 int PrimitiveDataInformationTest::minimumUnsignedBits(quint64 value)
0098 {
0099     if (value == 0) {
0100         return 1;
0101     }
0102     for (int i = 63; i >= 0; --i) {
0103         if ((value & (quint64(1) << i)) == (quint64(1) << i)) {
0104             return i + 1;
0105         }
0106     }
0107 
0108     QTEST_ASSERT(false);
0109     return 65;
0110 }
0111 
0112 void PrimitiveDataInformationTest::initTestCase()
0113 {
0114     KLocalizedString::setLanguages(QStringList() << QStringLiteral("C"));
0115     Kasten::StructureViewPreferences::setLocaleAwareDecimalFormatting(false); // this could mess with our expected results
0116     Kasten::StructureViewPreferences::setLocaleAwareFloatFormatting(false); // this could mess with our expected results
0117     QLocale locale(QLocale::C);
0118     locale.setNumberOptions(QLocale::OmitGroupSeparator);
0119     QLocale::setDefault(locale);
0120 
0121     LoggerWithContext lwc(nullptr, QString());
0122 
0123     PrimitiveDataType type = PrimitiveDataType::START;
0124     while (type < PrimitiveDataType::Bitfield) {
0125         basic.insert(type, PrimitiveFactory::newInstance(QStringLiteral("prim"), type, lwc));
0126         type = static_cast<PrimitiveDataType>(static_cast<int>(type) + 1);
0127     }
0128     boolBitfield = new BoolBitfieldDataInformation(QStringLiteral("bitfield"), 24);
0129     unsignedBitfield = new UnsignedBitfieldDataInformation(QStringLiteral("bitfield"), 24);
0130     signedBitfield = new SignedBitfieldDataInformation(QStringLiteral("bitfield"), 24);
0131 }
0132 
0133 namespace {
0134 template <PrimitiveDataType Type>
0135 void valueCompareHelper(typename PrimitiveInfo<Type>::valueType value, QString bin,
0136                         QString hex, QString dec, QString oct)
0137 {
0138     QCOMPARE(PrimitiveInfo<Type>::Methods::staticValueString(value, 2), bin);
0139     QCOMPARE(PrimitiveInfo<Type>::Methods::staticValueString(value, 16), hex);
0140     QCOMPARE(PrimitiveInfo<Type>::Methods::staticValueString(value, 10), dec);
0141     QCOMPARE(PrimitiveInfo<Type>::Methods::staticValueString(value, 8), oct);
0142 }
0143 
0144 template <PrimitiveDataType first, PrimitiveDataType second>
0145 void valueCompareHelperUnsigned(typename PrimitiveInfo<first>::valueType value, const QString& bin,
0146                                 const QString& hex, const QString& dec, const QString& oct, const QString& boolBase)
0147 {
0148     QCOMPARE(PrimitiveInfo<first>::Methods::staticValueString(value, 2), bin);
0149     QCOMPARE(PrimitiveInfo<first>::Methods::staticValueString(value, 16), hex);
0150     QCOMPARE(PrimitiveInfo<first>::Methods::staticValueString(value, 10), dec);
0151     QCOMPARE(PrimitiveInfo<first>::Methods::staticValueString(value, 8), oct);
0152 
0153     QCOMPARE(PrimitiveInfo<second>::Methods::staticValueString(value, 2),
0154              value > 1 ? boolBase.arg(bin) : boolBase);
0155     QCOMPARE(PrimitiveInfo<second>::Methods::staticValueString(value, 16),
0156              value > 1 ? boolBase.arg(hex) : boolBase);
0157     QCOMPARE(PrimitiveInfo<second>::Methods::staticValueString(value, 10),
0158              value > 1 ? boolBase.arg(dec) : boolBase);
0159     QCOMPARE(PrimitiveInfo<second>::Methods::staticValueString(value, 8),
0160              value > 1 ? boolBase.arg(oct) : boolBase);
0161 }
0162 
0163 }
0164 
0165 void PrimitiveDataInformationTest::testValueStringInt()
0166 {
0167     QFETCH(qint64, value);
0168     QFETCH(QString, binStr);
0169     QFETCH(QString, hexStr);
0170     QFETCH(QString, decStr);
0171     QFETCH(QString, octStr);
0172 
0173     int minSize = minimumSignedBits(value);
0174     // qDebug() << "need" << minSize << "bit to represent" << value;
0175     // run once with locale aware, and once without
0176     for (int i = 0; i <= 1; ++i) {
0177         Kasten::StructureViewPreferences::setLocaleAwareDecimalFormatting(bool(i));
0178 
0179         if (minSize <= 8) {
0180             valueCompareHelper<PrimitiveDataType::Int8>(qint8(value), binStr, hexStr, decStr, octStr);
0181         }
0182         if (minSize <= 16) {
0183             valueCompareHelper<PrimitiveDataType::Int16>(qint16(value), binStr, hexStr, decStr, octStr);
0184         }
0185         if (minSize <= 32) {
0186             valueCompareHelper<PrimitiveDataType::Int32>(qint32(value), binStr, hexStr, decStr, octStr);
0187         }
0188         if (minSize <= 64) {
0189             valueCompareHelper<PrimitiveDataType::Int64>(qint64(value), binStr, hexStr, decStr, octStr);
0190         }
0191 
0192         // check bitfield now
0193         SignedBitfieldDataInformation bitfield(QStringLiteral("signed"), minSize);
0194         bitfield.setValue(value);
0195         for (uint width = minSize; width <= 64U; ++width) {
0196             bitfield.setWidth(width);
0197             bitfield.mWasAbleToRead = true;
0198             Kasten::StructureViewPreferences::setSignedDisplayBase(2);
0199             QCOMPARE(bitfield.valueString(), binStr);
0200             Kasten::StructureViewPreferences::setSignedDisplayBase(16);
0201             QCOMPARE(bitfield.valueString(), hexStr);
0202             Kasten::StructureViewPreferences::setSignedDisplayBase(10);
0203             QCOMPARE(bitfield.valueString(), decStr);
0204             Kasten::StructureViewPreferences::setSignedDisplayBase(8);
0205             QCOMPARE(bitfield.valueString(), octStr);
0206         }
0207     }
0208 }
0209 
0210 void PrimitiveDataInformationTest::testValueStringInt_data()
0211 {
0212     QTest::addColumn<qint64>("value");
0213     QTest::addColumn<QString>("binStr");
0214     QTest::addColumn<QString>("hexStr");
0215     QTest::addColumn<QString>("decStr");
0216     QTest::addColumn<QString>("octStr");
0217 
0218     QTest::newRow("0") << qint64(0) << "0b0" << "0x0" << "0" << "0o0";
0219     QTest::newRow("1") << qint64(1) << "0b1" << "0x1" << "1" << "0o1";
0220     QTest::newRow("2") << qint64(2) << "0b10" << "0x2" << "2" << "0o2";
0221     QTest::newRow("32") << qint64(32) << "0b100000" << "0x20" << "32" << "0o40";
0222     QTest::newRow("79") << qint64(79) << "0b1001111" << "0x4f" << "79" << "0o117";
0223     QTest::newRow("172") << qint64(172) << "0b10101100" // 8 chars -> no space
0224                          << "0xac" << "172" << "0o254";
0225     QTest::newRow("259") << qint64(259) << "0b1 00000011" // 9 chars -> space
0226                          << "0x103" << "259" << "0o403";
0227     QTest::newRow("50448") << qint64(50448) << "0b11000101 00010000" // 16 chars -> no space
0228                            << "0xc510" << "50448" << "0o142420";
0229     QTest::newRow("126832") << qint64(126832) << "0b1 11101111 01110000" // 17 chars -> space
0230                             << "0x1ef70" << "126832" << "0o367560";
0231     // maximum
0232     QTest::newRow("qint8::max()") << qint64(std::numeric_limits<qint8>::max())
0233                                   << "0b1111111" << "0x7f" << "127" << "0o177";
0234     QTest::newRow("qint16::max()") << qint64(std::numeric_limits<qint16>::max())
0235                                    << "0b1111111 11111111" << "0x7fff" << "32767" << "0o77777";
0236     QTest::newRow("qint32::max()") << qint64(std::numeric_limits<qint32>::max())
0237                                    << "0b1111111 11111111 11111111 11111111" << "0x7fffffff" << "2147483647"
0238                                    << "0o177 77777777";
0239     QTest::newRow("qint64::max()") << qint64(std::numeric_limits<qint64>::max())
0240                                    << "0b1111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111"
0241                                    << "0x7fffffff ffffffff" << "9223372036854775807" << "0o77777 77777777 77777777";
0242     // negative
0243     QTest::newRow("-1") << qint64(-1) << "-0b1" << "-0x1" << "-1" << "-0o1";
0244     QTest::newRow("-2") << qint64(-2) << "-0b10" << "-0x2" << "-2" << "-0o2";
0245     QTest::newRow("-32") << qint64(-32) << "-0b100000" << "-0x20" << "-32" << "-0o40";
0246     QTest::newRow("-79") << qint64(-79) << "-0b1001111" << "-0x4f" << "-79" << "-0o117";
0247     QTest::newRow("-172") << qint64(-172) << "-0b10101100" << "-0xac" << "-172" << "-0o254";
0248     QTest::newRow("-259") << qint64(-259) << "-0b1 00000011" << "-0x103" << "-259" << "-0o403";
0249     ;
0250     QTest::newRow("-50448") << qint64(-50448) << "-0b11000101 00010000"
0251                             << "-0xc510" << "-50448" << "-0o142420";
0252     QTest::newRow("-126832") << qint64(-126832) << "-0b1 11101111 01110000"
0253                              << "-0x1ef70" << "-126832" << "-0o367560";
0254     // -1 * postive maximum
0255     QTest::newRow("-qint8::max()") << qint64(-std::numeric_limits<qint8>::max())
0256                                    << "-0b1111111" << "-0x7f" << "-127" << "-0o177";
0257     QTest::newRow("-qint16::max()") << qint64(-std::numeric_limits<qint16>::max())
0258                                     << "-0b1111111 11111111" << "-0x7fff" << "-32767" << "-0o77777";
0259     ;
0260     QTest::newRow("-qint32::max()") << qint64(-std::numeric_limits<qint32>::max())
0261                                     << "-0b1111111 11111111 11111111 11111111" << "-0x7fffffff" << "-2147483647"
0262                                     << "-0o177 77777777";
0263     QTest::newRow("-qint64::max()") << qint64(-std::numeric_limits<qint64>::max())
0264                                     << "-0b1111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111"
0265                                     << "-0x7fffffff ffffffff" << "-9223372036854775807" << "-0o77777 77777777 77777777";
0266 
0267     // negative minimum
0268     QTest::newRow("qint8::min()") << qint64(std::numeric_limits<qint8>::min())
0269                                   << "-0b10000000" << "-0x80" << "-128" << "-0o200";
0270     QTest::newRow("qint16::min()") << qint64(std::numeric_limits<qint16>::min())
0271                                    << "-0b10000000 00000000" << "-0x8000" << "-32768" << "-0o100000";
0272     QTest::newRow("qint32::min()") << qint64(std::numeric_limits<qint32>::min())
0273                                    << "-0b10000000 00000000 00000000 00000000" << "-0x80000000" << "-2147483648"
0274                                    << "-0o200 00000000";
0275     QTest::newRow("qint64::min()") << qint64(std::numeric_limits<qint64>::min())
0276                                    << "-0b10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
0277                                    << "-0x80000000 00000000" << "-9223372036854775808" << "-0o100000 00000000 00000000";
0278 }
0279 
0280 void PrimitiveDataInformationTest::testFromVariant()
0281 {
0282     bool ok = false;
0283     FloatDataInformationMethods::fromVariant(QVariant(float(42.0F)), &ok);
0284     QCOMPARE(ok, true); // float in range
0285     FloatDataInformationMethods::fromVariant(QVariant(double(42.0)), &ok);
0286     QCOMPARE(ok, true); // double should be fine too
0287     FloatDataInformationMethods::fromVariant(QVariant(double(std::numeric_limits<float>::max())), &ok);
0288     QCOMPARE(ok, true); // float max as a double should work too
0289     FloatDataInformationMethods::fromVariant(QVariant(std::numeric_limits<float>::quiet_NaN()), &ok);
0290     QCOMPARE(ok, true); // nan should be fine too
0291     FloatDataInformationMethods::fromVariant(QVariant(std::numeric_limits<double>::quiet_NaN()), &ok);
0292     QCOMPARE(ok, true); // double nan gets mapped to float nan
0293     FloatDataInformationMethods::fromVariant(QVariant(QStringLiteral("abc")), &ok);
0294     QCOMPARE(ok, false); // bad data type
0295     FloatDataInformationMethods::fromVariant(QVariant(std::numeric_limits<double>::max()), &ok);
0296     QCOMPARE(ok, false); // out of range
0297 
0298     DoubleDataInformationMethods::fromVariant(QVariant(float(42.0F)), &ok);
0299     QCOMPARE(ok, true); // float should be fine too QVariant::type() == Float
0300     DoubleDataInformationMethods::fromVariant(QVariant(std::numeric_limits<double>::max()), &ok);
0301     QCOMPARE(ok, true); // double
0302     DoubleDataInformationMethods::fromVariant(QVariant(std::numeric_limits<float>::quiet_NaN()), &ok);
0303     QCOMPARE(ok, true); // nan should be fine too
0304     DoubleDataInformationMethods::fromVariant(QVariant(std::numeric_limits<double>::quiet_NaN()), &ok);
0305     QCOMPARE(ok, true); // double nan gets mapped to float nan
0306     DoubleDataInformationMethods::fromVariant(QVariant(QStringLiteral("abc")), &ok);
0307     QCOMPARE(ok, false); // bad data type
0308     // TODO test other types!
0309 
0310 }
0311 
0312 void PrimitiveDataInformationTest::testValueStringUIntAndBool()
0313 {
0314     // this test will fail if translations are loaded
0315     QFETCH(quint64, value);
0316     QFETCH(QString, binStr);
0317     QFETCH(QString, hexStr);
0318     QFETCH(QString, decStr);
0319     QFETCH(QString, octStr);
0320 
0321     int minSize = minimumUnsignedBits(value);
0322     // qDebug() << "need" << minSize << "bit to represent" << value;
0323     QString boolBase;
0324     if (value == 0) {
0325         boolBase = QStringLiteral("false");
0326     } else if (value == 1) {
0327         boolBase = QStringLiteral("true");
0328     } else {
0329         boolBase = QStringLiteral("true (%1)");
0330     }
0331     // run once with locale aware, and once without
0332     for (int i = 0; i <= 1; ++i) {
0333         Kasten::StructureViewPreferences::setLocaleAwareDecimalFormatting(bool(i));
0334 
0335         if (minSize <= 8) {
0336             valueCompareHelperUnsigned<PrimitiveDataType::UInt8, PrimitiveDataType::Bool8>(quint8(value), binStr, hexStr,
0337                                                                                            decStr, octStr, boolBase);
0338         }
0339         if (minSize <= 16) {
0340             valueCompareHelperUnsigned<PrimitiveDataType::UInt16, PrimitiveDataType::Bool16>(quint16(value), binStr, hexStr,
0341                                                                                              decStr, octStr, boolBase);
0342         }
0343         if (minSize <= 32) {
0344             valueCompareHelperUnsigned<PrimitiveDataType::UInt32, PrimitiveDataType::Bool32>(quint32(value), binStr, hexStr,
0345                                                                                              decStr, octStr, boolBase);
0346         }
0347         if (minSize <= 64) {
0348             valueCompareHelperUnsigned<PrimitiveDataType::UInt64, PrimitiveDataType::Bool64>(quint64(value), binStr, hexStr,
0349                                                                                              decStr, octStr, boolBase);
0350         }
0351 
0352         // check bitfield now
0353         UnsignedBitfieldDataInformation bitfield(QStringLiteral("unsigned"), minSize);
0354         BoolBitfieldDataInformation boolBitfield(QStringLiteral("bool"), minSize);
0355         bitfield.setValue(value);
0356         boolBitfield.setValue(value);
0357         bitfield.mWasAbleToRead = true;
0358         boolBitfield.mWasAbleToRead = true;
0359         for (uint width = minSize; width <= 64U; ++width) {
0360             bitfield.setWidth(width);
0361             bitfield.setWidth(width);
0362             Kasten::StructureViewPreferences::setUnsignedDisplayBase(2);
0363             QCOMPARE(bitfield.valueString(), binStr);
0364             QCOMPARE(boolBitfield.valueString(), value > 1 ? boolBase.arg(binStr) : boolBase);
0365             Kasten::StructureViewPreferences::setUnsignedDisplayBase(16);
0366             QCOMPARE(bitfield.valueString(), hexStr);
0367             QCOMPARE(boolBitfield.valueString(), value > 1 ? boolBase.arg(hexStr) : boolBase);
0368             Kasten::StructureViewPreferences::setUnsignedDisplayBase(10);
0369             QCOMPARE(bitfield.valueString(), decStr);
0370             QCOMPARE(boolBitfield.valueString(), value > 1 ? boolBase.arg(decStr) : boolBase);
0371             Kasten::StructureViewPreferences::setUnsignedDisplayBase(8);
0372             QCOMPARE(bitfield.valueString(), octStr);
0373             QCOMPARE(boolBitfield.valueString(), value > 1 ? boolBase.arg(octStr) : boolBase);
0374         }
0375     }
0376 }
0377 
0378 void PrimitiveDataInformationTest::testValueStringUIntAndBool_data()
0379 {
0380     QTest::addColumn<quint64>("value");
0381     QTest::addColumn<QString>("binStr");
0382     QTest::addColumn<QString>("hexStr");
0383     QTest::addColumn<QString>("decStr");
0384     QTest::addColumn<QString>("octStr");
0385 
0386     QTest::newRow("0") << quint64(0) << "0b0" << "0x0" << "0" << "0o0";
0387     QTest::newRow("1") << quint64(1) << "0b1" << "0x1" << "1" << "0o1";
0388     QTest::newRow("2") << quint64(2) << "0b10" << "0x2" << "2" << "0o2";
0389     QTest::newRow("32") << quint64(32) << "0b100000" << "0x20" << "32" << "0o40";
0390     QTest::newRow("79") << quint64(79) << "0b1001111" << "0x4f" << "79" << "0o117";
0391     QTest::newRow("172") << quint64(172) << "0b10101100" // 8 chars -> no space
0392                          << "0xac" << "172" << "0o254";
0393     QTest::newRow("259") << quint64(259) << "0b1 00000011" // 9 chars -> space
0394                          << "0x103" << "259" << "0o403";
0395     QTest::newRow("50448") << quint64(50448) << "0b11000101 00010000" // 16 chars -> no space
0396                            << "0xc510" << "50448" << "0o142420";
0397     QTest::newRow("126832") << quint64(126832) << "0b1 11101111 01110000" // 17 chars -> space
0398                             << "0x1ef70" << "126832" << "0o367560";
0399     // maximum
0400     QTest::newRow("quint8::max()") << quint64(std::numeric_limits<quint8>::max())
0401                                    << "0b11111111" << "0xff" << "255" << "0o377";
0402     QTest::newRow("quint16::max()") << quint64(std::numeric_limits<quint16>::max())
0403                                     << "0b11111111 11111111" << "0xffff" << "65535" << "0o177777";
0404     QTest::newRow("quint32::max()") << quint64(std::numeric_limits<quint32>::max())
0405                                     << "0b11111111 11111111 11111111 11111111" << "0xffffffff" << "4294967295"
0406                                     << "0o377 77777777";
0407     QTest::newRow("quint64::max()") << quint64(std::numeric_limits<quint64>::max())
0408                                     << "0b11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111"
0409                                     << "0xffffffff ffffffff" << "18446744073709551615" << "0o177777 77777777 77777777";
0410 }
0411 
0412 namespace {
0413 QString charString(quint32 i)
0414 {
0415     QString charString;
0416     if (i == '\n') {
0417         charString = QStringLiteral("\\n");
0418     } else if (i == '\t') {
0419         charString = QStringLiteral("\\t");
0420     } else if (i == '\r') {
0421         charString = QStringLiteral("\\r");
0422     } else if (i == '\f') {
0423         charString = QStringLiteral("\\f");
0424     } else if (i == '\0') {
0425         charString = QStringLiteral("\\0");
0426     } else if (i == '\v') {
0427         charString = QStringLiteral("\\v");
0428     } else if (i == '\b') {
0429         charString = QStringLiteral("\\b");
0430     } else if (i == '\a') {
0431         charString = QStringLiteral("\\a");
0432     } else {
0433         QChar unicode = (i > 127) ? QChar::ReplacementCharacter : QChar(i, 0);
0434         if (unicode.isPrint()) {
0435             charString = QString(unicode);
0436         } else {
0437             charString = QString(QChar::ReplacementCharacter);
0438         }
0439     }
0440     // qDebug doesn't output unicode!
0441     // printf("The string for char %#x is: %s\n", i, charString.toUtf8().data());
0442     return charString;
0443 }
0444 }
0445 
0446 void PrimitiveDataInformationTest::testValueStringChar()
0447 {
0448     Kasten::StructureViewPreferences::setShowCharNumericalValue(false);
0449     Kasten::StructureViewPreferences::setLocaleAwareDecimalFormatting(false);
0450     // we don't want the numeric value now
0451     for (int i = 0; i < 256; ++i) {
0452         QString expected = QStringLiteral("'%1'").arg(charString(i));
0453         QCOMPARE(CharDataInformationMethods::staticValueString(i), expected);
0454     }
0455 
0456     Kasten::StructureViewPreferences::setShowCharNumericalValue(true);
0457     Kasten::StructureViewPreferences::setCharDisplayBase(16);
0458     for (int i = 0; i < 256; ++i) {
0459         QString expected = QStringLiteral("'%1' (0x%2)").arg(charString(i),
0460                                                              QString::number(i, 16));
0461         QCOMPARE(CharDataInformationMethods::staticValueString(i), expected);
0462     }
0463 
0464     Kasten::StructureViewPreferences::setCharDisplayBase(10);
0465     for (int i = 0; i < 256; ++i) {
0466         QString expected = QStringLiteral("'%1' (%2)").arg(charString(i),
0467                                                            QString::number(i, 10));
0468         QCOMPARE(CharDataInformationMethods::staticValueString(i), expected);
0469     }
0470 
0471     Kasten::StructureViewPreferences::setCharDisplayBase(2);
0472     for (int i = 0; i < 256; ++i) {
0473         QString expected = QStringLiteral("'%1' (0b%2)").arg(charString(i),
0474                                                              QString::number(i, 2));
0475         QCOMPARE(CharDataInformationMethods::staticValueString(i), expected);
0476     }
0477 
0478     Kasten::StructureViewPreferences::setCharDisplayBase(8);
0479     for (int i = 0; i < 256; ++i) {
0480         QString expected = QStringLiteral("'%1' (0o%2)").arg(charString(i),
0481                                                              QString::number(i, 8));
0482         QCOMPARE(CharDataInformationMethods::staticValueString(i), expected);
0483     }
0484 
0485     // TODO octal
0486 }
0487 
0488 void PrimitiveDataInformationTest::testValueStringDouble()
0489 {
0490     // TODO implement
0491 }
0492 
0493 void PrimitiveDataInformationTest::testValueStringFloat()
0494 {
0495     // TODO implement
0496 }
0497 
0498 void PrimitiveDataInformationTest::testToAndFromVariant()
0499 {
0500     // TODO implement
0501 }
0502 
0503 void PrimitiveDataInformationTest::testGetAndSetValue()
0504 {
0505     QFETCH(PrimitiveDataInformation*, data);
0506     QFETCH(AllPrimitiveTypes, newVal);
0507     QFETCH(AllPrimitiveTypes, expected);
0508 
0509     std::unique_ptr<PrimitiveDataInformation> clone(data->clone());
0510     clone->setValue(newVal);
0511     QCOMPARE(clone->value(), expected);
0512 }
0513 
0514 template <typename signedType, typename unsignedType>
0515 void PrimitiveDataInformationTest::addRowsGetAndSetSigned(PrimitiveDataType type, const char* name)
0516 {
0517     QString msg = QString::fromUtf8(name);
0518     QTest::newRow(msg.arg(QStringLiteral("-325")).toUtf8().constData())
0519         << basic[type] << AllPrimitiveTypes(-325) << AllPrimitiveTypes(signedType(-325));
0520     QTest::newRow(msg.arg(QStringLiteral("0")).toUtf8().constData())
0521         << basic[type] << AllPrimitiveTypes(0) << AllPrimitiveTypes(signedType(0));
0522     QTest::newRow(msg.arg(QStringLiteral("-1")).toUtf8().constData())
0523         << basic[type] << AllPrimitiveTypes(-1) << AllPrimitiveTypes(signedType(-1));
0524     QTest::newRow(msg.arg(QStringLiteral("357891")).toUtf8().constData())
0525         << basic[type] << AllPrimitiveTypes(357891) << AllPrimitiveTypes(signedType(357891));
0526 
0527     QTest::newRow(msg.arg(QStringLiteral("max")).toUtf8().constData())
0528         << basic[type] << AllPrimitiveTypes(std::numeric_limits<signedType>::max())
0529         << AllPrimitiveTypes(signedType(std::numeric_limits<signedType>::max()));
0530     QTest::newRow(msg.arg(QStringLiteral("min")).toUtf8().constData())
0531         << basic[type] << AllPrimitiveTypes(std::numeric_limits<signedType>::min())
0532         << AllPrimitiveTypes(signedType(std::numeric_limits<signedType>::min()));
0533     QTest::newRow(msg.arg(QStringLiteral("u_max")).toUtf8().constData())
0534         << basic[type] << AllPrimitiveTypes(std::numeric_limits<unsignedType>::max())
0535         << AllPrimitiveTypes(signedType(std::numeric_limits<unsignedType>::max()));
0536     QTest::newRow(msg.arg(QStringLiteral("u_min")).toUtf8().constData())
0537         << basic[type] << AllPrimitiveTypes(std::numeric_limits<unsignedType>::min())
0538         << AllPrimitiveTypes(signedType(std::numeric_limits<unsignedType>::min()));
0539 }
0540 
0541 template <typename signedType>
0542 void PrimitiveDataInformationTest::addRowsGetAndSetUnsigned(PrimitiveDataType type, const char* name)
0543 {
0544     QString msg = QString::fromUtf8(name);
0545     QTest::newRow(msg.arg(QStringLiteral("-325")).toUtf8().constData())
0546         << basic[type] << AllPrimitiveTypes(-325) << AllPrimitiveTypes(signedType(-325));
0547     QTest::newRow(msg.arg(QStringLiteral("0")).toUtf8().constData())
0548         << basic[type] << AllPrimitiveTypes(0) << AllPrimitiveTypes(signedType(0));
0549     QTest::newRow(msg.arg(QStringLiteral("-1")).toUtf8().constData())
0550         << basic[type] << AllPrimitiveTypes(-1) << AllPrimitiveTypes(signedType(-1));
0551     QTest::newRow(msg.arg(QStringLiteral("357891")).toUtf8().constData())
0552         << basic[type] << AllPrimitiveTypes(357891) << AllPrimitiveTypes(signedType(357891));
0553 
0554     QTest::newRow(msg.arg(QStringLiteral("max")).toUtf8().constData())
0555         << basic[type] << AllPrimitiveTypes(std::numeric_limits<signedType>::max())
0556         << AllPrimitiveTypes(signedType(std::numeric_limits<signedType>::max()));
0557     QTest::newRow(msg.arg(QStringLiteral("min")).toUtf8().constData())
0558         << basic[type] << AllPrimitiveTypes(std::numeric_limits<signedType>::min())
0559         << AllPrimitiveTypes(signedType(std::numeric_limits<signedType>::min()));
0560 }
0561 
0562 void PrimitiveDataInformationTest::testGetAndSetValue_data()
0563 {
0564     QTest::addColumn<PrimitiveDataInformation*>("data");
0565     QTest::addColumn<AllPrimitiveTypes>("newVal");
0566     QTest::addColumn<AllPrimitiveTypes>("expected");
0567 
0568     addRowsGetAndSetSigned<qint8, quint8>(PrimitiveDataType::Int8, "int8: %1");
0569     addRowsGetAndSetSigned<qint16, quint16>(PrimitiveDataType::Int16, "int8: %1");
0570     addRowsGetAndSetSigned<qint32, quint32>(PrimitiveDataType::Int32, "int8: %1");
0571     addRowsGetAndSetSigned<qint64, quint64>(PrimitiveDataType::Int64, "int8: %1");
0572 }
0573 
0574 void PrimitiveDataInformationTest::cleanupTestCase()
0575 {
0576     qDeleteAll(basic);
0577     delete signedBitfield;
0578     delete unsignedBitfield;
0579     delete boolBitfield;
0580 }
0581 
0582 QTEST_GUILESS_MAIN(PrimitiveDataInformationTest)
0583 
0584 #include "primitivedatainformationtest.moc"