Warning, file /utilities/okteta/kasten/controllers/test/primitivedatainformationtest.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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