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

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 <QTest>
0010 
0011 #include <Okteta/ByteArrayModel>
0012 #include <Okteta/Byte>
0013 
0014 #include "testutils.hpp"
0015 
0016 #include "view/structures/datatypes/uniondatainformation.hpp"
0017 #include "view/structures/datatypes/topleveldatainformation.hpp"
0018 #include "view/structures/datatypes/primitivefactory.hpp"
0019 #include "view/structures/datatypes/primitive/bitfield/unsignedbitfielddatainformation.hpp"
0020 // Std
0021 #include <memory>
0022 
0023 class UnionDataInformationTest : public QObject
0024 {
0025     Q_OBJECT
0026 
0027 private Q_SLOTS:
0028     void initTestCase();
0029     void testSize();
0030     void testReadData1();
0031     void testReadData1_data();
0032 
0033 private:
0034     std::unique_ptr<Okteta::ByteArrayModel> model;
0035 };
0036 
0037 /** In binary:
0038  *  00010010 00110100 01010110 01111000
0039  *  10011010 10111100 11011110 11110000
0040  */
0041 static constexpr Okteta::Byte testData[8] = {
0042     0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0
0043 };
0044 
0045 void UnionDataInformationTest::initTestCase()
0046 {
0047     model.reset(new Okteta::ByteArrayModel(testData, sizeof(testData)));
0048     model->setAutoDelete(false);
0049     QCOMPARE(model->size(), Okteta::Size(8));
0050 }
0051 
0052 void UnionDataInformationTest::testSize()
0053 {
0054     LoggerWithContext lwc(nullptr, QString());
0055 
0056     UnionDataInformation empty(QStringLiteral("empty"));
0057     QCOMPARE(empty.size(), BitCount32(0));
0058     QVector<DataInformation*> size54;
0059     size54 << PrimitiveFactory::newInstance(QStringLiteral("8"), PrimitiveDataType::Bool8, lwc);
0060     size54 << PrimitiveFactory::newInstance(QStringLiteral("16"), PrimitiveDataType::Int16, lwc);
0061     size54 << PrimitiveFactory::newInstance(QStringLiteral("32"), PrimitiveDataType::Float, lwc);
0062     size54 << new UnsignedBitfieldDataInformation(QStringLiteral("54"), 54);
0063     UnionDataInformation fourChildren(QStringLiteral("four"), size54);
0064     QCOMPARE(fourChildren.size(), BitCount32(54));
0065 }
0066 
0067 void UnionDataInformationTest::testReadData1()
0068 {
0069     LoggerWithContext lwc(nullptr, QString());
0070 
0071     PrimitiveDataInformation* b8 = PrimitiveFactory::newInstance(QStringLiteral("8"), PrimitiveDataType::Bool8, lwc);
0072     PrimitiveDataInformation* u32 = PrimitiveFactory::newInstance(QStringLiteral("32"), PrimitiveDataType::UInt32, lwc);
0073     PrimitiveDataInformation* i16 = PrimitiveFactory::newInstance(QStringLiteral("16"), PrimitiveDataType::Int16, lwc);
0074     auto* u54 = new UnsignedBitfieldDataInformation(QStringLiteral("54"), 54);
0075     QVector<DataInformation*> children;
0076     children << b8 << u32 << i16 << u54;
0077     auto* un = new UnionDataInformation(QStringLiteral("un"), children);
0078     un->setByteOrder(DataInformation::DataInformationEndianess::EndianessLittle);
0079     TopLevelDataInformation top(un);
0080     // read from bit 0
0081     QFETCH(uint, address);
0082     QFETCH(quint8, offset);
0083     QFETCH(quint64, bitsRemaining);
0084     // update needed before read
0085     top.scriptHandler()->updateDataInformation(un);
0086     qint64 read = un->readData(model.get(), address, bitsRemaining, &offset);
0087     QFETCH(qint64, readBitsTotal);
0088     QCOMPARE(read, readBitsTotal);
0089     QFETCH(quint8, offsetAfterRead);
0090     QCOMPARE(offset, offsetAfterRead);
0091     QFETCH(bool, unWasAble);
0092     QCOMPARE(un->wasAbleToRead(), unWasAble);
0093 
0094     QFETCH(quint8, b8Expected);
0095     QFETCH(bool, b8WasAble);
0096     QFETCH(qint16, i16Expected);
0097     QFETCH(bool, i16WasAble);
0098     QFETCH(quint32, u32Expected);
0099     QFETCH(bool, u32WasAble);
0100     QFETCH(quint64, u54Expected);
0101     QFETCH(bool, u54WasAble);
0102 
0103     QCOMPARE(b8->value().value<quint8>(), b8Expected);
0104     QCOMPARE(b8->wasAbleToRead(), b8WasAble);
0105     QCOMPARE(i16->value().value<qint16>(), i16Expected);
0106     QCOMPARE(i16->wasAbleToRead(), i16WasAble);
0107     QCOMPARE(u32->value().value<quint32>(), u32Expected);
0108     QCOMPARE(u32->wasAbleToRead(), u32WasAble);
0109     QCOMPARE(u54->value().value<quint64>(), u54Expected);
0110     QCOMPARE(u54->wasAbleToRead(), u54WasAble);
0111 }
0112 
0113 void UnionDataInformationTest::testReadData1_data()
0114 {
0115     QTest::addColumn<uint>("address");
0116     QTest::addColumn<quint8>("offset");
0117     QTest::addColumn<quint64>("bitsRemaining"); // XXX get rid of this argument?
0118 
0119     QTest::addColumn<qint64>("readBitsTotal");
0120     QTest::addColumn<quint8>("offsetAfterRead");
0121     QTest::addColumn<bool>("unWasAble");
0122 
0123     QTest::addColumn<quint8>("b8Expected");
0124     QTest::addColumn<bool>("b8WasAble");
0125     QTest::addColumn<qint16>("i16Expected");
0126     QTest::addColumn<bool>("i16WasAble");
0127     QTest::addColumn<quint32>("u32Expected");
0128     QTest::addColumn<bool>("u32WasAble");
0129     QTest::addColumn<quint64>("u54Expected");
0130     QTest::addColumn<bool>("u54WasAble");
0131 
0132     /* In little endian:
0133      *  11110000 11011110 10111100 10011010
0134      *  01111000 01010110 00110100 00010010
0135      */
0136     QTest::newRow("0 bytes 0 bits") << 0U << quint8(0) << quint64(64) << qint64(54) << quint8(6) << true
0137         /* now b8 and i16 */ << quint8(0x12U) << true << qint16(0x3412) << true
0138         /* u32 and u54 */ << quint32(0x78563412U) << true << Q_UINT64_C(0x1ebc9a78563412) << true;
0139     // shifted by two bytes in little endian:
0140     // 11110000 11011110 10111100 10011010 01111000 01010110 00110100 000100xx
0141     QTest::newRow("0 bytes 2 bits") << 0U << quint8(2) << quint64(62) << qint64(54) << quint8(0) << true
0142         /* b8 */ << Utils::binary<quint8>("00 000100") << true
0143         /* i16 */ << Utils::binary<qint16>("10 00110100 000100") << true
0144         /* u32 */ << Utils::binary<quint32>("10 01111000 01010110 00110100 000100") << true
0145         /* u54 */ << Utils::binary<quint64>("11011110 10111100 10011010 01111000 01010110 00110100 000100") << true;
0146 
0147     // now so that the 54bit value fits in exactly, i.e. 10 bits shifted
0148     // shifted by 10 bytes in little endian:
0149     // 11110000 11011110 10111100 10011010 01111000 01010110 001101xx xxxxxxxx
0150     QTest::newRow("1 bytes 2 bits") << 1U << quint8(2) << quint64(54) << qint64(54) << quint8(0) << true
0151         /* b8 */ << Utils::binary<quint8>("10 001101") << true
0152         /* i16 */ << Utils::binary<qint16>("00 01010110 001101") << true
0153         /* u32 */ << Utils::binary<quint32>("00 10011010 01111000 01010110 001101") << true
0154         /* u54 */ << Utils::binary<quint64>("11110000 11011110 10111100 10011010 01111000 01010110 001101") << true;
0155 
0156     // now make the 54 bit value go past eof (11 bits)
0157     // shifted by 10 bytes in little endian:
0158     // 11110000 11011110 10111100 10011010 01111000 01010110 00110xxx xxxxxxxx
0159     QTest::newRow("1 bytes 3 bits") << 1U << quint8(3) << quint64(53) << qint64(-1) << quint8(3) << false
0160         /* b8 */ << Utils::binary<quint8>("110 00110") << true
0161         /* i16 */ << Utils::binary<qint16>("000 01010110 00110") << true
0162         /* u32 */ << Utils::binary<quint32>("100 10011010 01111000 01010110 00110") << true
0163         /* u54 */ << Utils::binary<quint64>("0") << false;
0164 }
0165 
0166 QTEST_GUILESS_MAIN(UnionDataInformationTest)
0167 
0168 #include "uniondatainformationtest.moc"