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: 2013 Alex Richardson <alex.richardson@gmx.de>
0005  *
0006  *  SPDX-License-Identifier: LGPL-2.1-or-later
0007  */
0008 
0009 #include <QTest>
0010 
0011 #include <limits>
0012 
0013 #include <Okteta/ByteArrayModel>
0014 #include "view/structures/datatypes/topleveldatainformation.hpp"
0015 #include "view/structures/datatypes/structuredatainformation.hpp"
0016 #include "view/structures/datatypes/primitive/primitivetemplateinfo.hpp"
0017 
0018 class LockToOffsetTest : public QObject
0019 {
0020     Q_OBJECT
0021 
0022 private Q_SLOTS:
0023     void initTestCase();
0024     void testReadingNecessary_data();
0025     void testReadingNecessary();
0026     void cleanupTestCase();
0027 
0028 private:
0029     TopLevelDataInformation* newStructure(Okteta::AbstractByteArrayModel* lastModel, Okteta::Address lastReadOffset);
0030 
0031 private:
0032     Okteta::ByteArrayModel* model;
0033     Okteta::ByteArrayModel* model2;
0034 };
0035 
0036 const unsigned char testData[128] =
0037 {
0038     0x17, 0xa7, 0x0b, 0xa7, 0x8d, 0x96, 0x15, 0x9e,
0039     0xc0, 0x75, 0x02, 0x5b, 0xfe, 0xa4, 0xf5, 0x44,
0040     0x66, 0xbc, 0xb0, 0x1e, 0x84, 0x47, 0x35, 0xd1,
0041     0xcf, 0x5f, 0x4b, 0xdb, 0x72, 0x2d, 0xe8, 0x89,
0042     0xd4, 0xf3, 0x31, 0x61, 0x8a, 0x46, 0x00, 0x4a,
0043     0xbb, 0x02, 0xa5, 0xb9, 0xa6, 0x9a, 0xfe, 0x0c,
0044     0x56, 0xae, 0x2a, 0xdb, 0xf5, 0x5f, 0xac, 0xc4,
0045     0xbf, 0xf7, 0x9f, 0x31, 0x25, 0x87, 0xbb, 0xf9,
0046     0x7b, 0xec, 0x5b, 0x05, 0x32, 0x5b, 0x4f, 0xee,
0047     0x5d, 0xf5, 0xa7, 0x03, 0x8f, 0xa5, 0x0f, 0xe6,
0048     0x53, 0x39, 0xc1, 0x48, 0x99, 0x6d, 0x0c, 0x58,
0049     0x64, 0xac, 0x89, 0x89, 0x33, 0x44, 0x83, 0xae,
0050     0x30, 0xde, 0xb3, 0x63, 0x39, 0x03, 0x51, 0x96,
0051     0xf8, 0xf8, 0x99, 0x87, 0x9e, 0xa8, 0x6d, 0xf1,
0052     0xe1, 0x2e, 0x3a, 0x7a, 0x9b, 0x46, 0xd2, 0x00,
0053     0xf2, 0x5c, 0x89, 0x26, 0xa0, 0x0c, 0xd4, 0xd1
0054 };
0055 
0056 const unsigned char testData2[128] =
0057 {
0058     0x4c, 0x4a, 0x64, 0x02, 0x98, 0x65, 0xb8, 0x56,
0059     0x94, 0x57, 0xd8, 0x4b, 0x02, 0x12, 0xc3, 0x65,
0060     0xad, 0xe2, 0xad, 0x0a, 0x69, 0xbb, 0x73, 0xec,
0061     0xa7, 0x0a, 0x14, 0x1c, 0xc4, 0xe1, 0x7c, 0x11,
0062     0x2b, 0xe0, 0x13, 0xc3, 0x45, 0xcc, 0x1a, 0xd9,
0063     0x23, 0xf2, 0x24, 0x25, 0x04, 0xe7, 0x8b, 0xb1,
0064     0xc9, 0x38, 0xbb, 0x33, 0xf4, 0x2f, 0x1f, 0x9b,
0065     0x39, 0x34, 0xb7, 0xfd, 0x15, 0x33, 0x0e, 0x40,
0066     0x13, 0x22, 0x03, 0x58, 0xee, 0x1d, 0x32, 0x11,
0067     0x0f, 0x56, 0x36, 0x13, 0x3e, 0xc1, 0xc4, 0x07,
0068     0xfa, 0x80, 0x3a, 0xee, 0xaf, 0x5a, 0x89, 0xe8,
0069     0x8e, 0x41, 0xe5, 0xa3, 0x74, 0xf4, 0xe3, 0x88,
0070     0x16, 0xe6, 0xe0, 0x04, 0x04, 0x12, 0x15, 0x13,
0071     0x69, 0x4b, 0x27, 0xa7, 0x0d, 0xeb, 0xae, 0x07,
0072     0x6b, 0xe9, 0xf5, 0x1a, 0x43, 0x7e, 0x02, 0xd1,
0073     0xbf, 0xe8, 0x74, 0x34, 0xdc, 0x57, 0xbc, 0xf2
0074 };
0075 
0076 void LockToOffsetTest::initTestCase()
0077 {
0078     model = new Okteta::ByteArrayModel(testData, sizeof(testData));
0079     model->setAutoDelete(false);
0080     model2 = new Okteta::ByteArrayModel(testData2, sizeof(testData2));
0081     model2->setAutoDelete(false);
0082 }
0083 
0084 void LockToOffsetTest::cleanupTestCase()
0085 {
0086     delete model;
0087     delete model2;
0088 }
0089 
0090 TopLevelDataInformation* LockToOffsetTest::newStructure(Okteta::AbstractByteArrayModel* lastModel, Okteta::Address lastReadOffset)
0091 {
0092     QVector<DataInformation*> children;
0093     children.append(new UInt16DataInformation(QStringLiteral("first")));
0094     children.append(new UInt64DataInformation(QStringLiteral("second")));
0095     DataInformation* data = new StructureDataInformation(QStringLiteral("container"), children);
0096     data->setByteOrder(DataInformation::DataInformationEndianess::EndianessBig);
0097     auto* top = new TopLevelDataInformation(data);
0098     top->mLastModel = lastModel;
0099     if (lastModel) {
0100         top->newModelActivated(lastModel);
0101     }
0102     top->mLastReadOffset = lastReadOffset;
0103     return top;
0104 }
0105 
0106 Q_DECLARE_METATYPE(Okteta::ArrayChangeMetricsList)
0107 
0108 static inline void addRow(const char* tag, TopLevelDataInformation* structure, Okteta::Address addr,
0109                           Okteta::AbstractByteArrayModel* model, const Okteta::ArrayChangeMetricsList& changes, bool expected)
0110 {
0111     QTest::newRow(tag) << structure << addr << model << changes << expected;
0112 }
0113 
0114 static Okteta::ArrayChangeMetricsList oneReplacement(int start, int length, int replacementSize)
0115 {
0116     return Okteta::ArrayChangeMetricsList {
0117         Okteta::ArrayChangeMetrics::asReplacement(start, length, replacementSize)
0118     };
0119 }
0120 
0121 void LockToOffsetTest::testReadingNecessary_data()
0122 {
0123     QTest::addColumn<TopLevelDataInformation*>("structure");
0124     QTest::addColumn<Okteta::Address>("address");
0125     QTest::addColumn<Okteta::AbstractByteArrayModel*>("model");
0126     QTest::addColumn<Okteta::ArrayChangeMetricsList>("changes");
0127     QTest::addColumn<bool>("expected");
0128     Okteta::ArrayChangeMetricsList noChanges;
0129 
0130     TopLevelDataInformation* top = newStructure(nullptr, 5);
0131     addRow("new model, same offset, no changes", top, 5, model, noChanges, true);
0132 
0133     top = newStructure(model, 5);
0134     addRow("same model, different offset, no changes", top, 6, model, noChanges, true);
0135 
0136     top = newStructure(model, 5);
0137     addRow("same model, same offset, no changes", top, 5, model, noChanges, false);
0138 
0139     top = newStructure(model, 5);
0140     top->lockPositionToOffset(5, model);
0141     addRow("same model, same offset (because of locking), no changes", top, 50, model, noChanges, false);
0142 
0143     top = newStructure(model, 5);
0144     top->newModelActivated(model2);
0145     addRow("different model, same offset, no changes", top, 5, model2, noChanges, true);
0146 
0147     top = newStructure(model, TopLevelDataInformation::INVALID_OFFSET);
0148     addRow("same model, invalid offset before, no changes", top, 5, model2, noChanges, true);
0149 
0150     top = newStructure(model, 5);
0151     addRow("same model, same offset, changes before", top, 5, model, oneReplacement(0, 4, 4), false);
0152 
0153     top = newStructure(model, 5);
0154     addRow("same model, same offset, changes before (right until start)", top, 5, model, oneReplacement(0, 5, 5), false);
0155 
0156     top = newStructure(model, 5);
0157     addRow("same model, same offset, changes before (1 byte removed!)", top, 5, model, oneReplacement(0, 5, 4), true);
0158 
0159     top = newStructure(model, 5);
0160     addRow("same model, same offset, changes before (1 byte added!)", top, 5, model, oneReplacement(0, 1, 2), true);
0161 
0162     top = newStructure(model, 5);
0163     addRow("same model, same offset, changes 2 bytes after (1 byte removed!)", top, 5, model, oneReplacement(16, 5, 4), false);
0164     top = newStructure(model, 5);
0165     addRow("same model, same offset, changes 1 byte after (1 byte removed!)", top, 5, model, oneReplacement(15, 5, 4), false);
0166 
0167     top = newStructure(model, 5);
0168     addRow("same model, same offset, changes 2 bytes after (1 byte added!)", top, 5, model, oneReplacement(16, 1, 2), false);
0169     top = newStructure(model, 5);
0170     addRow("same model, same offset, changes 1 byte after (1 byte added!)", top, 5, model, oneReplacement(15, 1, 2), false);
0171 
0172 }
0173 
0174 void LockToOffsetTest::testReadingNecessary()
0175 {
0176     QFETCH(Okteta::AbstractByteArrayModel*, model);
0177     QFETCH(TopLevelDataInformation*, structure);
0178     QFETCH(Okteta::ArrayChangeMetricsList, changes);
0179     QFETCH(Okteta::Address, address);
0180     QFETCH(bool, expected);
0181     if (structure->isLockedFor(model)) {
0182         address = structure->lockPositionFor(model);
0183     }
0184     QCOMPARE(structure->isReadingNecessary(model, address, changes), expected);
0185     structure->read(model, address, changes, false);
0186     // no changes after read -> no reading necessary
0187     QVERIFY(!structure->isReadingNecessary(model, address, Okteta::ArrayChangeMetricsList()));
0188     delete structure;
0189 }
0190 
0191 QTEST_GUILESS_MAIN(LockToOffsetTest)
0192 
0193 #include "locktooffsettest.moc"