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"