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

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/array/arraydatainformation.hpp"
0010 #include "view/structures/datatypes/array/primitivearraydata.hpp"
0011 #include "view/structures/datatypes/strings/stringdatainformation.hpp"
0012 #include "view/structures/datatypes/topleveldatainformation.hpp"
0013 #include "view/structures/datatypes/primitive/primitivetemplateinfo.hpp"
0014 #include "view/structures/datatypes/primitive/enumdatainformation.hpp"
0015 #include "view/structures/datatypes/primitive/flagdatainformation.hpp"
0016 #include "view/structures/datatypes/primitive/bitfield/boolbitfielddatainformation.hpp"
0017 #include "view/structures/datatypes/primitive/bitfield/signedbitfielddatainformation.hpp"
0018 #include "view/structures/datatypes/primitive/bitfield/unsignedbitfielddatainformation.hpp"
0019 #include "view/structures/datatypes/primitivefactory.hpp"
0020 #include "view/structures/datatypes/uniondatainformation.hpp"
0021 #include "view/structures/datatypes/structuredatainformation.hpp"
0022 // Qt
0023 #include <QTest>
0024 // Std
0025 #include <memory>
0026 #include <utility>
0027 
0028 struct ExpectedResults
0029 {
0030     ExpectedResults()
0031         : isTopLevel(false)
0032         , isEnum(false)
0033         , isStruct(false)
0034         , isUnion(false)
0035         , isArray(false)
0036         , isBitfield(false)
0037         , isPrimitive(false)
0038         , isString(false)
0039         , isDummy(false)
0040         , hasChildren(false)
0041     {
0042         columnFlags[DataInformation::ColumnName] = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
0043         columnFlags[DataInformation::ColumnType] = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
0044         columnFlags[DataInformation::ColumnValue] = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
0045         noFileColumnFlags[DataInformation::ColumnName] = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
0046         noFileColumnFlags[DataInformation::ColumnType] = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
0047         noFileColumnFlags[DataInformation::ColumnValue] = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
0048     }
0049     DataInformationBase* parent = nullptr;
0050     BitCount32 size = 0;
0051     bool isTopLevel : 1;
0052     bool isEnum : 1;
0053     bool isStruct : 1;
0054     bool isUnion : 1;
0055     bool isArray : 1;
0056     bool isBitfield : 1;
0057     bool isPrimitive : 1;
0058     bool isString : 1;
0059     bool isDummy : 1;
0060     bool hasChildren : 1;
0061     Qt::ItemFlags columnFlags[DataInformation::COLUMN_COUNT];
0062     Qt::ItemFlags noFileColumnFlags[DataInformation::COLUMN_COUNT];
0063 };
0064 
0065 class BasicDataInformationTest : public QObject
0066 {
0067     Q_OBJECT
0068 
0069 private:
0070     void basicTest(DataInformationBase* data, const ExpectedResults& expected) const;
0071 
0072 private Q_SLOTS:
0073     void initTestCase();
0074     void testPrimitives();
0075     void testBitfields();
0076     void testStructs();
0077     void testUnions();
0078     void testArrays();
0079     void testEnums();
0080     void testString();
0081     void testDummy();
0082     void testTopLevel();
0083     void cleanupTestCase();
0084 
0085 private:
0086     QVector<PrimitiveDataInformation*> primitives;
0087     QVector<AbstractBitfieldDataInformation*> bitfields;
0088     TopLevelDataInformation* topLevel;
0089     StructureDataInformation* emptyStruct;
0090     StructureDataInformation* structWithChildren;
0091     UnionDataInformation* emptyUnion;
0092     UnionDataInformation* unionWithChildren;
0093     ArrayDataInformation* emptyPrimitiveArray;
0094     ArrayDataInformation* emptyComplexArray;
0095     ArrayDataInformation* primitiveArrayWithChildren;
0096     ArrayDataInformation* complexArrayWithChildren;
0097     StringDataInformation* emptyString;
0098     DummyDataInformation* dummy;
0099     FlagDataInformation* flagData;
0100     EnumDataInformation* enumData;
0101 };
0102 
0103 #if 0
0104 
0105 #ifdef NDEBUG
0106 #pragma message("NDEBUG defined")
0107 #else
0108 #pragma message("NDEBUG not defined")
0109 #endif
0110 
0111 #ifdef DEBUG
0112 #pragma message("DEBUG defined")
0113 #else
0114 #pragma message("DEBUG not defined")
0115 #endif
0116 
0117 #ifdef QT_NO_DEBUG
0118 #pragma message("QT_NO_DEBUG defined")
0119 #else
0120 #pragma message("QT_NO_DEBUG not defined")
0121 #endif
0122 
0123 #ifdef QT_DEBUG
0124 #pragma message("QT_DEBUG defined")
0125 #else
0126 #pragma message("QT_DEBUG not defined")
0127 #endif
0128 
0129 #endif
0130 
0131 namespace {
0132 template <typename T> void castChecker(bool isValid, DataInformationBase* data, const T* constValue, T* nonConstValue)
0133 {
0134     if (isValid) {
0135         QCOMPARE(constValue, static_cast<const T*>(data));
0136         QCOMPARE(nonConstValue, static_cast<T*>(data));
0137     } else {
0138         QCOMPARE(constValue, static_cast<const T*>(nullptr));
0139         QCOMPARE(nonConstValue, static_cast<T*>(nullptr));
0140     }
0141 }
0142 #define CAST_CHECKER(isValid, value, func, type) do { \
0143         const DataInformationBase* constData = data; \
0144         const type* constVal = constData->func(); \
0145         type* nonConstVal = data->func(); \
0146         castChecker(isValid, value, constVal, nonConstVal); \
0147     } while (0)
0148 
0149 }
0150 void BasicDataInformationTest::basicTest(DataInformationBase* data, const ExpectedResults& expected) const
0151 {
0152     QVERIFY(data);
0153     QCOMPARE(data->isTopLevel(), expected.isTopLevel);
0154     if (expected.isTopLevel) {
0155         CAST_CHECKER(true, data, asTopLevel, TopLevelDataInformation);
0156         CAST_CHECKER(false, data, asArray, ArrayDataInformation);
0157         CAST_CHECKER(false, data, asBitfield, AbstractBitfieldDataInformation);
0158         CAST_CHECKER(false, data, asDataInformation, DataInformation);
0159         CAST_CHECKER(false, data, asDummy, DummyDataInformation);
0160         CAST_CHECKER(false, data, asEnum, EnumDataInformation);
0161         CAST_CHECKER(false, data, asPrimitive, PrimitiveDataInformation);
0162         CAST_CHECKER(false, data, asString, StringDataInformation);
0163         CAST_CHECKER(false, data, asStruct, StructureDataInformation);
0164         CAST_CHECKER(false, data, asUnion, UnionDataInformation);
0165         return; // no more can be done with a TopLeveDataInformation
0166     }
0167 
0168     CAST_CHECKER(false, data, asTopLevel, TopLevelDataInformation);
0169     CAST_CHECKER(true, data, asDataInformation, DataInformation);
0170 
0171     QCOMPARE(data->isArray(), expected.isArray);
0172     if (expected.isArray) {
0173         CAST_CHECKER(true, data, asArray, ArrayDataInformation);
0174     } else {
0175         CAST_CHECKER(false, data, asArray, ArrayDataInformation);
0176     }
0177 
0178     QCOMPARE(data->isBitfield(), expected.isBitfield);
0179     if (expected.isBitfield) {
0180         CAST_CHECKER(true, data, asBitfield, AbstractBitfieldDataInformation);
0181     } else {
0182         CAST_CHECKER(false, data, asBitfield, AbstractBitfieldDataInformation);
0183     }
0184 
0185     QCOMPARE(data->isEnum(), expected.isEnum);
0186     if (expected.isEnum) {
0187         CAST_CHECKER(true, data, asEnum, EnumDataInformation);
0188     } else {
0189         CAST_CHECKER(false, data, asEnum, EnumDataInformation);
0190     }
0191 
0192     QCOMPARE(data->isPrimitive(), expected.isPrimitive);
0193     if (expected.isPrimitive) {
0194         CAST_CHECKER(true, data, asPrimitive, PrimitiveDataInformation);
0195     } else {
0196         CAST_CHECKER(false, data, asPrimitive, PrimitiveDataInformation);
0197     }
0198 
0199     QCOMPARE(data->isStruct(), expected.isStruct);
0200     if (expected.isStruct) {
0201         CAST_CHECKER(true, data, asStruct, StructureDataInformation);
0202     } else {
0203         CAST_CHECKER(false, data, asStruct, StructureDataInformation);
0204     }
0205 
0206     QCOMPARE(data->isUnion(), expected.isUnion);
0207     if (expected.isUnion) {
0208         CAST_CHECKER(true, data, asUnion, UnionDataInformation);
0209     } else {
0210         CAST_CHECKER(false, data, asUnion, UnionDataInformation);
0211     }
0212 
0213     QCOMPARE(data->isString(), expected.isString);
0214     if (expected.isString) {
0215         CAST_CHECKER(true, data, asString, StringDataInformation);
0216     } else {
0217         CAST_CHECKER(false, data, asString, StringDataInformation);
0218     }
0219 
0220     QCOMPARE(data->isDummy(), expected.isDummy);
0221     if (expected.isDummy) {
0222         CAST_CHECKER(true, data, asDummy, DummyDataInformation);
0223         return; // the other checks cannot be done with a dummy
0224     }
0225 
0226     CAST_CHECKER(false, data, asDummy, DummyDataInformation);
0227 
0228     DataInformation* dataInf = data->asDataInformation();
0229     QVERIFY(dataInf);
0230 
0231     QCOMPARE(dataInf->size(), expected.size);
0232     QCOMPARE(dataInf->parent(), expected.parent);
0233 
0234     DataInformation* clone1 = (dataInf->clone());
0235     std::unique_ptr<TopLevelDataInformation> top(new TopLevelDataInformation(clone1));
0236     QCOMPARE(clone1->parent(), top.get()); // top takes ownership of clone1
0237     QCOMPARE(top->actualDataInformation(), clone1);
0238 
0239     std::unique_ptr<DataInformation> clone2(clone1->clone());
0240     QVERIFY(clone2->parent() == nullptr); // cloning should reset parent to NULL, else we get dangling pointers
0241 
0242     QCOMPARE(dataInf->flags(DataInformation::ColumnName, true), expected.columnFlags[DataInformation::ColumnName]);
0243     QCOMPARE(dataInf->flags(DataInformation::ColumnType, true), expected.columnFlags[DataInformation::ColumnType]);
0244     QCOMPARE(dataInf->flags(DataInformation::ColumnValue, true), expected.columnFlags[DataInformation::ColumnValue]);
0245 
0246     QCOMPARE(dataInf->flags(DataInformation::ColumnName, false), expected.noFileColumnFlags[DataInformation::ColumnName]);
0247     QCOMPARE(dataInf->flags(DataInformation::ColumnType, false), expected.noFileColumnFlags[DataInformation::ColumnType]);
0248     QCOMPARE(dataInf->flags(DataInformation::ColumnValue, false), expected.noFileColumnFlags[DataInformation::ColumnValue]);
0249 }
0250 
0251 void BasicDataInformationTest::initTestCase()
0252 {
0253 //  qRegisterMetaType<const DataInformation*>();
0254 //  qRegisterMetaType<DataInformation*>();
0255     LoggerWithContext lwc(nullptr, QString());
0256 
0257     PrimitiveDataType type = PrimitiveDataType::START;
0258     while (type < PrimitiveDataType::Bitfield) {
0259         primitives.append(PrimitiveFactory::newInstance(QStringLiteral("prim"), type, lwc));
0260         type = static_cast<PrimitiveDataType>(static_cast<int>(type) + 1);
0261     }
0262     QCOMPARE(PrimitiveFactory::newInstance(QStringLiteral("invalid"), PrimitiveDataType::Bitfield, lwc), static_cast<PrimitiveDataInformation*>(nullptr));
0263     QCOMPARE(PrimitiveFactory::newInstance(QStringLiteral("invalid"), QStringLiteral("invalid_type"), lwc), static_cast<PrimitiveDataInformation*>(nullptr));
0264     bitfields.append(new BoolBitfieldDataInformation(QStringLiteral("bitfield"), 24));
0265     bitfields.append(new UnsignedBitfieldDataInformation(QStringLiteral("bitfield"), 24));
0266     bitfields.append(new SignedBitfieldDataInformation(QStringLiteral("bitfield"), 24));
0267 
0268     emptyStruct = new StructureDataInformation(QStringLiteral("emptyStruct"));
0269     QVector<DataInformation*> structChildren;
0270     structChildren << PrimitiveFactory::newInstance(QStringLiteral("prim"), PrimitiveDataType::UInt32, lwc)
0271                    << PrimitiveFactory::newInstance(QStringLiteral("prim2"), PrimitiveDataType::UInt64, lwc);
0272     structWithChildren = new StructureDataInformation(QStringLiteral("structWithChildren"), structChildren);
0273 
0274     emptyUnion = new UnionDataInformation(QStringLiteral("emptyUnion"));
0275     QVector<DataInformation*> unionChildren;
0276     unionChildren << PrimitiveFactory::newInstance(QStringLiteral("prim"), PrimitiveDataType::UInt32, lwc)
0277                   << PrimitiveFactory::newInstance(QStringLiteral("prim2"), PrimitiveDataType::UInt64, lwc);
0278     unionWithChildren = new UnionDataInformation(QStringLiteral("unionWithChildren"), unionChildren);
0279 
0280     emptyPrimitiveArray = new ArrayDataInformation(QStringLiteral("emptyPrimitiveArray"), 0, PrimitiveFactory::newInstance(QStringLiteral("prim"), PrimitiveDataType::UInt32, lwc));
0281     emptyComplexArray = new ArrayDataInformation(QStringLiteral("emptyComplexArray"), 0, structWithChildren->clone());
0282     primitiveArrayWithChildren = new ArrayDataInformation(QStringLiteral("primitiveArrayWithChildren"), 2, PrimitiveFactory::newInstance(QStringLiteral("prim"), PrimitiveDataType::UInt32, lwc));
0283     complexArrayWithChildren = new ArrayDataInformation(QStringLiteral("complexArrayWithChildren"), 2, structWithChildren->clone());
0284 
0285     QMap<AllPrimitiveTypes, QString> enumVals;
0286     enumVals[1] = QStringLiteral("one");
0287     enumVals[2] = QStringLiteral("two");
0288     enumVals[4] = QStringLiteral("four");
0289     EnumDefinition::Ptr edef(new EnumDefinition(enumVals, QStringLiteral("eDef"), PrimitiveDataType::UInt32));
0290     flagData = new FlagDataInformation(QStringLiteral("flagData"), PrimitiveFactory::newInstance(QStringLiteral("prim"), PrimitiveDataType::UInt32, lwc), edef);
0291     enumData = new EnumDataInformation(QStringLiteral("enumData"), PrimitiveFactory::newInstance(QStringLiteral("prim"), PrimitiveDataType::UInt32, lwc), edef);
0292     emptyString = new StringDataInformation(QStringLiteral("string"), StringDataInformation::StringType::ASCII);
0293     dummy = new DummyDataInformation(nullptr);
0294     topLevel = new TopLevelDataInformation(new DummyDataInformation(nullptr));
0295 }
0296 
0297 void BasicDataInformationTest::testBitfields()
0298 {
0299     ExpectedResults exp;
0300     exp.isPrimitive = true;
0301     exp.isBitfield = true;
0302     exp.size = 24;
0303     exp.columnFlags[DataInformation::ColumnValue] = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
0304     for (auto* bitField : std::as_const(bitfields)) {
0305         basicTest(bitField, exp);
0306     }
0307 }
0308 
0309 void BasicDataInformationTest::testPrimitives()
0310 {
0311     ExpectedResults exp;
0312     exp.isPrimitive = true;
0313     exp.columnFlags[DataInformation::ColumnValue] = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
0314     for (int i = 0; i < primitives.size(); ++i) {
0315         PrimitiveDataInformation* data = primitives.at(i);
0316         PrimitiveDataType t = data->type();
0317         QCOMPARE(t, PrimitiveDataType(static_cast<PrimitiveDataType>(i)));
0318         QCOMPARE(data->type(), PrimitiveDataType(static_cast<PrimitiveDataType>(i)));
0319         if (t == PrimitiveDataType::Bool8 || t ==  PrimitiveDataType::Int8 || t == PrimitiveDataType::UInt8 || t == PrimitiveDataType::Char) {
0320             exp.size = 8;
0321         } else if (t == PrimitiveDataType::Bool16 || t == PrimitiveDataType::Int16 || t == PrimitiveDataType::UInt16) {
0322             exp.size = 16;
0323         } else if (t == PrimitiveDataType::Bool32 || t == PrimitiveDataType::Int32 || t == PrimitiveDataType::UInt32 || t == PrimitiveDataType::Float) {
0324             exp.size = 32;
0325         } else if (t == PrimitiveDataType::Bool64 || t == PrimitiveDataType::Int64 || t == PrimitiveDataType::UInt64 || t == PrimitiveDataType::Double) {
0326             exp.size = 64;
0327         } else {
0328             QVERIFY(false);
0329         }
0330         basicTest(data, exp);
0331     }
0332 }
0333 
0334 void BasicDataInformationTest::testArrays()
0335 {
0336     ExpectedResults exp;
0337     exp.isArray = true;
0338     exp.size = 0;
0339     basicTest(emptyComplexArray, exp);
0340     basicTest(emptyPrimitiveArray, exp);
0341     exp.hasChildren = true;
0342     exp.size = 64;
0343     basicTest(primitiveArrayWithChildren, exp);
0344     exp.size = 96 * 2;
0345     basicTest(complexArrayWithChildren, exp);
0346 }
0347 
0348 void BasicDataInformationTest::testEnums()
0349 {
0350     ExpectedResults exp;
0351     exp.isPrimitive = true;
0352     exp.isEnum = true;
0353     exp.size = 32;
0354     exp.columnFlags[DataInformation::ColumnValue] = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
0355     basicTest(enumData, exp);
0356     basicTest(flagData, exp);
0357 }
0358 
0359 void BasicDataInformationTest::testStructs()
0360 {
0361     ExpectedResults exp;
0362     exp.isStruct = true;
0363     exp.size = 0;
0364     basicTest(emptyStruct, exp);
0365     exp.hasChildren = true;
0366     exp.size = 96;
0367     basicTest(structWithChildren, exp);
0368 }
0369 
0370 void BasicDataInformationTest::testUnions()
0371 {
0372     ExpectedResults exp;
0373     exp.isUnion = true;
0374     exp.size = 0;
0375     basicTest(emptyUnion, exp);
0376     exp.hasChildren = true;
0377     exp.size = 64;
0378     basicTest(unionWithChildren, exp);
0379 }
0380 
0381 void BasicDataInformationTest::testDummy()
0382 {
0383     ExpectedResults exp;
0384     exp.isDummy = true;
0385     exp.size = 0;
0386     basicTest(dummy, exp);
0387 }
0388 
0389 void BasicDataInformationTest::testString()
0390 {
0391     ExpectedResults exp;
0392     exp.isString = true;
0393     exp.size = 0;
0394     basicTest(emptyString, exp);
0395 }
0396 
0397 void BasicDataInformationTest::testTopLevel()
0398 {
0399     ExpectedResults exp;
0400     exp.isTopLevel = true;
0401     basicTest(topLevel, exp);
0402 }
0403 
0404 void BasicDataInformationTest::cleanupTestCase()
0405 {
0406     qDeleteAll(primitives);
0407     qDeleteAll(bitfields);
0408     delete emptyStruct;
0409     delete structWithChildren;
0410     delete emptyUnion;
0411     delete unionWithChildren;
0412     delete emptyPrimitiveArray;
0413     delete emptyComplexArray;
0414     delete primitiveArrayWithChildren;
0415     delete complexArrayWithChildren;
0416     delete flagData;
0417     delete enumData;
0418     delete emptyString;
0419     delete dummy;
0420     delete topLevel;
0421 }
0422 
0423 QTEST_GUILESS_MAIN(BasicDataInformationTest)
0424 
0425 #include "basicdatainformationtest.moc"