File indexing completed on 2024-04-21 03:56:06

0001 /*
0002     SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef PROXY_MODEL_TEST_H
0008 #define PROXY_MODEL_TEST_H
0009 
0010 #include <QAbstractProxyModel>
0011 #include <QTest>
0012 
0013 #include "dynamictreemodel.h"
0014 #include "indexfinder.h"
0015 #include "modelcommander.h"
0016 #include "modelspy.h"
0017 #include "persistentchangelist.h"
0018 
0019 #include "proxymodeltestsuite_export.h"
0020 
0021 typedef QList<QVariantList> SignalList;
0022 
0023 Q_DECLARE_METATYPE(SignalList)
0024 
0025 enum Persistence {
0026     LazyPersistence,
0027     ImmediatePersistence,
0028 };
0029 
0030 enum SourceModel {
0031     DynamicTree,
0032     IntermediateProxy,
0033 };
0034 
0035 class PROXYMODELTESTSUITE_EXPORT BuiltinTestDataInterface
0036 {
0037 public:
0038     virtual ~BuiltinTestDataInterface()
0039     {
0040     }
0041 
0042 private:
0043     virtual void testInsertWhenEmptyData() = 0;
0044     virtual void testInsertInRootData() = 0;
0045     virtual void testInsertInTopLevelData() = 0;
0046     virtual void testInsertInSecondLevelData() = 0;
0047 
0048     virtual void testRemoveFromRootData() = 0;
0049     virtual void testRemoveFromTopLevelData() = 0;
0050     virtual void testRemoveFromSecondLevelData() = 0;
0051 
0052     virtual void testMoveFromRootData() = 0;
0053     virtual void testMoveFromTopLevelData() = 0;
0054     virtual void testMoveFromSecondLevelData() = 0;
0055 
0056     virtual void testModifyInRootData() = 0;
0057     virtual void testModifyInTopLevelData() = 0;
0058     virtual void testModifyInSecondLevelData() = 0;
0059 };
0060 
0061 class PROXYMODELTESTSUITE_EXPORT BuiltinTestInterface : BuiltinTestDataInterface
0062 {
0063 public:
0064     ~BuiltinTestInterface() override
0065     {
0066     }
0067 
0068 private:
0069     virtual void testInsertWhenEmpty_data() = 0;
0070     virtual void testInsertWhenEmpty() = 0;
0071 
0072     virtual void testInsertInRoot_data() = 0;
0073     virtual void testInsertInRoot() = 0;
0074 
0075     virtual void testInsertInTopLevel_data() = 0;
0076     virtual void testInsertInTopLevel() = 0;
0077 
0078     virtual void testInsertInSecondLevel_data() = 0;
0079     virtual void testInsertInSecondLevel() = 0;
0080 
0081     virtual void testRemoveFromRoot_data() = 0;
0082     virtual void testRemoveFromRoot() = 0;
0083 
0084     virtual void testRemoveFromTopLevel_data() = 0;
0085     virtual void testRemoveFromTopLevel() = 0;
0086 
0087     virtual void testRemoveFromSecondLevel_data() = 0;
0088     virtual void testRemoveFromSecondLevel() = 0;
0089 
0090     virtual void testMoveFromRoot_data() = 0;
0091     virtual void testMoveFromRoot() = 0;
0092 
0093     virtual void testMoveFromTopLevel_data() = 0;
0094     virtual void testMoveFromTopLevel() = 0;
0095 
0096     virtual void testMoveFromSecondLevel_data() = 0;
0097     virtual void testMoveFromSecondLevel() = 0;
0098 
0099     virtual void testModifyInRoot_data() = 0;
0100     virtual void testModifyInRoot() = 0;
0101 
0102     virtual void testModifyInTopLevel_data() = 0;
0103     virtual void testModifyInTopLevel() = 0;
0104 
0105     virtual void testModifyInSecondLevel_data() = 0;
0106     virtual void testModifyInSecondLevel() = 0;
0107 };
0108 
0109 class PROXYMODELTESTSUITE_EXPORT ProxyModelTest : public QObject, protected BuiltinTestInterface
0110 {
0111     Q_OBJECT
0112 public:
0113     ProxyModelTest(QObject *parent = nullptr);
0114     ~ProxyModelTest() override
0115     {
0116     }
0117 
0118     void setLazyPersistence(Persistence persistence);
0119     void setUseIntermediateProxy(SourceModel sourceModel);
0120 
0121     DynamicTreeModel *rootModel() const
0122     {
0123         return m_rootModel;
0124     }
0125     QAbstractItemModel *sourceModel() const
0126     {
0127         return m_sourceModel;
0128     }
0129     QAbstractProxyModel *proxyModel() const
0130     {
0131         return m_proxyModel;
0132     }
0133     ModelSpy *modelSpy() const
0134     {
0135         return m_modelSpy;
0136     }
0137 
0138     PersistentIndexChange getChange(IndexFinder sourceFinder, int start, int end, int difference, bool toInvalid = false);
0139     QVariantList noSignal() const
0140     {
0141         return QVariantList() << NoSignal;
0142     }
0143     QVariantList getSignal(SignalType type, IndexFinder parentFinder, int start, int end) const
0144     {
0145         return QVariantList() << type << QVariant::fromValue(parentFinder) << start << end;
0146     }
0147     QVariantList getSignal(SignalType type, IndexFinder srcFinder, int start, int end, IndexFinder destFinder, int destStart) const
0148     {
0149         return QVariantList() << type << QVariant::fromValue(srcFinder) << start << end << QVariant::fromValue(destFinder) << destStart;
0150     }
0151     QVariantList getSignal(SignalType type, IndexFinder topLeftFinder, IndexFinder bottomRightFinder) const
0152     {
0153         return QVariantList() << type << QVariant::fromValue(topLeftFinder) << QVariant::fromValue(bottomRightFinder);
0154     }
0155 
0156 protected:
0157     virtual QAbstractProxyModel *getProxy() = 0;
0158 
0159     void doCleanupTestCase()
0160     {
0161         cleanupTestCase();
0162     }
0163     void doCleanup()
0164     {
0165         cleanup();
0166     }
0167 
0168 Q_SIGNALS:
0169     void testInsertWhenEmptyData() override;
0170     void testInsertInRootData() override;
0171     void testInsertInTopLevelData() override;
0172     void testInsertInSecondLevelData() override;
0173 
0174     void testRemoveFromRootData() override;
0175     void testRemoveFromTopLevelData() override;
0176     void testRemoveFromSecondLevelData() override;
0177 
0178     void testMoveFromRootData() override;
0179     void testMoveFromTopLevelData() override;
0180     void testMoveFromSecondLevelData() override;
0181 
0182     void testModifyInRootData() override;
0183     void testModifyInTopLevelData() override;
0184     void testModifyInSecondLevelData() override;
0185 
0186 protected Q_SLOTS:
0187     void testMappings();
0188     void verifyModel(const QModelIndex &parent, int start, int end);
0189     void verifyModel(const QModelIndex &parent, int start, int end, const QModelIndex &destParent, int dest);
0190     void verifyModel(const QModelIndex &topLeft, const QModelIndex &bottomRight);
0191 
0192 private Q_SLOTS:
0193     void init();
0194     void cleanup();
0195     void cleanupTestCase();
0196 
0197     void testEmptyModel();
0198     void testSourceReset();
0199     void testDestroyModel();
0200 
0201     void testInsertWhenEmpty_data() override
0202     {
0203         testInsertWhenEmptyData();
0204     }
0205     void testInsertWhenEmpty() override
0206     {
0207         doTest();
0208     }
0209 
0210     void testInsertInRoot_data() override
0211     {
0212         testInsertInRootData();
0213     }
0214     void testInsertInRoot() override
0215     {
0216         doTest();
0217     }
0218 
0219     void testInsertInTopLevel_data() override
0220     {
0221         testInsertInTopLevelData();
0222     }
0223     void testInsertInTopLevel() override
0224     {
0225         doTest();
0226     }
0227 
0228     void testInsertInSecondLevel_data() override
0229     {
0230         testInsertInSecondLevelData();
0231     }
0232     void testInsertInSecondLevel() override
0233     {
0234         doTest();
0235     }
0236 
0237     void testRemoveFromRoot_data() override
0238     {
0239         testRemoveFromRootData();
0240     }
0241     void testRemoveFromRoot() override
0242     {
0243         doTest();
0244     }
0245 
0246     void testRemoveFromTopLevel_data() override
0247     {
0248         testRemoveFromTopLevelData();
0249     }
0250     void testRemoveFromTopLevel() override
0251     {
0252         doTest();
0253     }
0254 
0255     void testRemoveFromSecondLevel_data() override
0256     {
0257         testRemoveFromSecondLevelData();
0258     }
0259     void testRemoveFromSecondLevel() override
0260     {
0261         doTest();
0262     }
0263 
0264     void testMoveFromRoot_data() override
0265     {
0266         testMoveFromRootData();
0267     }
0268     void testMoveFromRoot() override
0269     {
0270         doTest();
0271     }
0272 
0273     void testMoveFromTopLevel_data() override
0274     {
0275         testMoveFromTopLevelData();
0276     }
0277     void testMoveFromTopLevel() override
0278     {
0279         doTest();
0280     }
0281 
0282     void testMoveFromSecondLevel_data() override
0283     {
0284         testMoveFromSecondLevelData();
0285     }
0286     void testMoveFromSecondLevel() override
0287     {
0288         doTest();
0289     }
0290 
0291     void testModifyInRoot_data() override
0292     {
0293         testModifyInRootData();
0294     }
0295     void testModifyInRoot() override
0296     {
0297         doTest();
0298     }
0299 
0300     void testModifyInTopLevel_data() override
0301     {
0302         testModifyInTopLevelData();
0303     }
0304     void testModifyInTopLevel() override
0305     {
0306         doTest();
0307     }
0308 
0309     void testModifyInSecondLevel_data() override
0310     {
0311         testModifyInSecondLevelData();
0312     }
0313     void testModifyInSecondLevel() override
0314     {
0315         doTest();
0316     }
0317 
0318 protected:
0319     void connectTestSignals(QObject *receiver);
0320     void disconnectTestSignals(QObject *receiver);
0321 
0322     void connectProxy(QAbstractProxyModel *proxyModel);
0323     void doTestMappings(const QModelIndex &parent);
0324     void initRootModel(DynamicTreeModel *rootModel, const QString &currentTest, const QString &currentTag);
0325 
0326     void doTest();
0327     void handleSignal(QVariantList expected);
0328     QVariantList getResultSignal();
0329     int getChange(bool sameParent, int start, int end, int currentPosition, int destinationStart);
0330     QStringList dataTags() const
0331     {
0332         return m_dataTags;
0333     }
0334     void verifyExecutedTests();
0335 
0336 private:
0337     DynamicTreeModel *m_rootModel;
0338     QAbstractItemModel *m_sourceModel;
0339     QAbstractProxyModel *m_proxyModel;
0340     QAbstractProxyModel *m_intermediateProxyModel;
0341     ModelSpy *m_modelSpy;
0342     ModelCommander *m_modelCommander;
0343     QStringList m_dataTags;
0344     QStringList m_modelCommanderTags;
0345     QString m_currentTest;
0346 };
0347 
0348 class PROXYMODELTESTSUITE_EXPORT ProxyModelTestData : public QObject, BuiltinTestDataInterface
0349 {
0350     Q_OBJECT
0351 public:
0352     ProxyModelTestData(ProxyModelTest *parent = nullptr)
0353         : QObject(parent)
0354         , m_proxyModelTest(parent)
0355     {
0356     }
0357 
0358     static const char *failTag()
0359     {
0360         return "fail01";
0361     }
0362 
0363 protected:
0364     void dummyTestData()
0365     {
0366         QTest::addColumn<SignalList>("signalList");
0367         QTest::addColumn<PersistentChangeList>("changeList");
0368 
0369         QTest::newRow(failTag()) << SignalList() << PersistentChangeList();
0370         QSKIP("Test not implemented");
0371     }
0372 
0373     void skipTestData(const QString &name)
0374     {
0375         processTestName(name);
0376 
0377         QTest::addColumn<SignalList>("signalList");
0378         QTest::addColumn<PersistentChangeList>("changeList");
0379 
0380         QTest::newRow(name.toLatin1()) << (SignalList() << (QVariantList() << "skip")) << PersistentChangeList();
0381     }
0382 
0383     void processTestName(const QString &name)
0384     {
0385         if (m_currentTestFunction != QTest::currentTestFunction()) {
0386             m_testNames.clear();
0387             m_currentTestFunction = QTest::currentTestFunction();
0388         }
0389         m_testNames.insert(name);
0390     }
0391 
0392     QStringList namedTests()
0393     {
0394         return m_testNames.values();
0395     }
0396 
0397     void noopTest(const QString &name)
0398     {
0399         processTestName(name);
0400 
0401         QTest::newRow(name.toLatin1()) << SignalList() << PersistentChangeList();
0402     }
0403 
0404     void noopLayoutChangeTest(const QString &name)
0405     {
0406         processTestName(name);
0407 
0408         SignalList signalList;
0409 
0410         signalList << (QVariantList() << LayoutAboutToBeChanged);
0411         signalList << (QVariantList() << LayoutChanged);
0412 
0413         QTest::newRow(name.toLatin1()) << signalList << PersistentChangeList();
0414     }
0415 
0416     void testForwardingInsertData(const IndexFinder &indexFinder)
0417     {
0418         QTest::addColumn<SignalList>("signalList");
0419         QTest::addColumn<PersistentChangeList>("changeList");
0420 
0421         newInsertTest(QStringLiteral("insert01"), indexFinder, 0, 0, 10);
0422         newInsertTest(QStringLiteral("insert02"), indexFinder, 0, 9, 10);
0423         newInsertTest(QStringLiteral("insert03"), indexFinder, 10, 10, 10);
0424         newInsertTest(QStringLiteral("insert04"), indexFinder, 10, 19, 10);
0425         newInsertTest(QStringLiteral("insert05"), indexFinder, 4, 4, 10);
0426         newInsertTest(QStringLiteral("insert06"), indexFinder, 4, 13, 10);
0427         newInsertTest(QStringLiteral("insert07"), indexFinder, 0, 0, 10);
0428         newInsertTest(QStringLiteral("insert08"), indexFinder, 10, 10, 10);
0429         newInsertTest(QStringLiteral("insert09"), indexFinder, 4, 4, 10);
0430         newInsertTest(QStringLiteral("insert10"), indexFinder, 0, 4, 10);
0431         newInsertTest(QStringLiteral("insert11"), indexFinder, 10, 14, 10);
0432         newInsertTest(QStringLiteral("insert12"), indexFinder, 4, 8, 10);
0433         QList<int> rows = indexFinder.rows();
0434         rows.append(0);
0435         newInsertTest(QStringLiteral("insert13"), rows, 0, 0, 0);
0436         newInsertTest(QStringLiteral("insert14"), rows, 0, 9, 0);
0437         newInsertTest(QStringLiteral("insert15"), rows, 0, 4, 0);
0438         rows = indexFinder.rows();
0439         rows.append(9);
0440         newInsertTest(QStringLiteral("insert16"), rows, 0, 0, 0);
0441         newInsertTest(QStringLiteral("insert17"), rows, 0, 9, 0);
0442         newInsertTest(QStringLiteral("insert18"), rows, 0, 4, 0);
0443     }
0444 
0445     void testForwardingRemoveData(const IndexFinder &indexFinder)
0446     {
0447         QTest::addColumn<SignalList>("signalList");
0448         QTest::addColumn<PersistentChangeList>("changeList");
0449 
0450         newRemoveTest(QStringLiteral("remove01"), indexFinder, 0, 0, 10);
0451         newRemoveTest(QStringLiteral("remove02"), indexFinder, 0, 4, 10);
0452         newRemoveTest(QStringLiteral("remove03"), indexFinder, 9, 9, 10);
0453     }
0454 
0455     void testForwardingMoveData(const IndexFinder &srcFinder, const IndexFinder &destFinder)
0456     {
0457         QTest::addColumn<SignalList>("signalList");
0458         QTest::addColumn<PersistentChangeList>("changeList");
0459 
0460         //     noopLayoutChangeTest("move01");
0461         //     noopLayoutChangeTest("move02");
0462         //     noopLayoutChangeTest("move03");
0463         //     noopLayoutChangeTest("move04");
0464         //     noopLayoutChangeTest("move05");
0465 
0466         newMoveTest(QStringLiteral("move01"), srcFinder, 0, 0, 10, destFinder, 5);
0467         newMoveTest(QStringLiteral("move02"), srcFinder, 4, 4, 10, destFinder, 0);
0468         newMoveTest(QStringLiteral("move03"), srcFinder, 4, 4, 10, destFinder, 10);
0469         newMoveTest(QStringLiteral("move04"), srcFinder, 9, 9, 10, destFinder, 4);
0470         newMoveTest(QStringLiteral("move05"), srcFinder, 9, 9, 10, destFinder, 0);
0471     }
0472 
0473     void testForwardingModifyData(const IndexFinder &parentFinder)
0474     {
0475         QTest::addColumn<SignalList>("signalList");
0476         QTest::addColumn<PersistentChangeList>("changeList");
0477 
0478         newModifyTest(QStringLiteral("modify01"), parentFinder, 0, 0);
0479         newModifyTest(QStringLiteral("modify02"), parentFinder, 0, 4);
0480         newModifyTest(QStringLiteral("modify03"), parentFinder, 9, 9);
0481         newModifyTest(QStringLiteral("modify04"), parentFinder, 6, 9);
0482         newModifyTest(QStringLiteral("modify05"), parentFinder, 4, 4);
0483         newModifyTest(QStringLiteral("modify06"), parentFinder, 3, 7);
0484         newModifyTest(QStringLiteral("modify07"), parentFinder, 0, 9);
0485     }
0486 
0487     void newInsertTest(const QString &name, const IndexFinder &indexFinder, int start, int end, int rowCount)
0488     {
0489         processTestName(name);
0490 
0491         SignalList signalList;
0492         PersistentChangeList persistentList;
0493 
0494         signalList << m_proxyModelTest->getSignal(RowsAboutToBeInserted, indexFinder, start, end);
0495         signalList << m_proxyModelTest->getSignal(RowsInserted, indexFinder, start, end);
0496 
0497         if (rowCount - 1 + (end - start + 1) > end) {
0498             persistentList << m_proxyModelTest->getChange(indexFinder, start, rowCount - 1, end - start + 1);
0499         }
0500 
0501         QTest::newRow(name.toLatin1()) << signalList << persistentList;
0502     }
0503 
0504     void newRemoveTest(const QString &name, const IndexFinder &indexFinder, int start, int end, int rowCount)
0505     {
0506         processTestName(name);
0507 
0508         SignalList signalList;
0509         PersistentChangeList persistentList;
0510 
0511         signalList << m_proxyModelTest->getSignal(RowsAboutToBeRemoved, indexFinder, start, end);
0512         signalList << m_proxyModelTest->getSignal(RowsRemoved, indexFinder, start, end);
0513 
0514         persistentList << m_proxyModelTest->getChange(indexFinder, start, end, -1, true);
0515         if (rowCount - 1 != end) {
0516             persistentList << m_proxyModelTest->getChange(indexFinder, end + 1, rowCount - 1, -1 * (end - start + 1));
0517         }
0518 
0519         QTest::newRow(name.toLatin1()) << signalList << persistentList;
0520     }
0521 
0522     void newMoveTest(const QString &name, const IndexFinder &srcFinder, int start, int end, int rowCount, const IndexFinder &destFinder, int destStart)
0523     {
0524         Q_UNUSED(rowCount)
0525         processTestName(name);
0526 
0527         SignalList signalList;
0528         PersistentChangeList persistentList;
0529 
0530         //     signalList << m_proxyModelTest->getSignal(RowsAboutToBeMoved, srcFinder, start, end, destFinder, destStart);
0531         //     signalList << ( QVariantList() << LayoutAboutToBeChanged );
0532         //     signalList << m_proxyModelTest->getSignal(RowsMoved, srcFinder, start, end, destFinder, destStart);
0533         //     signalList << ( QVariantList() << LayoutChanged );
0534 
0535         signalList << (QVariantList() << LayoutAboutToBeChanged);
0536         signalList << (QVariantList() << LayoutChanged);
0537 
0538         const bool sameParent = (srcFinder == destFinder);
0539         const bool movingUp = (start > destStart);
0540 
0541         if (sameParent) {
0542             if (movingUp) {
0543                 persistentList << m_proxyModelTest->getChange(srcFinder, destStart, start - 1, end - start + 1);
0544                 persistentList << m_proxyModelTest->getChange(srcFinder, start, end, -1 * (start - destStart));
0545             } else {
0546                 persistentList << m_proxyModelTest->getChange(srcFinder, start, end, destStart - end - 1);
0547                 persistentList << m_proxyModelTest->getChange(srcFinder, end + 1, destStart - 1, -1 * (end - start + 1));
0548             }
0549         } else {
0550             if (movingUp) {
0551                 // TODO
0552             }
0553         }
0554 
0555         QTest::newRow(name.toLatin1()) << signalList << persistentList;
0556     }
0557 
0558     void newModifyTest(const QString &name, const IndexFinder &parentFinder, int top, int bottom)
0559     {
0560         processTestName(name);
0561 
0562         SignalList signalList;
0563 
0564         IndexFinder topLeftFinder = parentFinder;
0565         topLeftFinder.appendRow(top);
0566 
0567         IndexFinder bottomRightFinder = parentFinder;
0568         bottomRightFinder.appendRow(bottom);
0569 
0570         signalList << m_proxyModelTest->getSignal(DataChanged, topLeftFinder, bottomRightFinder);
0571 
0572         QTest::newRow(name.toLatin1()) << signalList << PersistentChangeList();
0573     }
0574 
0575     void noop_testInsertWhenEmptyData()
0576     {
0577         QTest::addColumn<SignalList>("signalList");
0578         QTest::addColumn<PersistentChangeList>("changeList");
0579 
0580         noopTest(QStringLiteral("insert01"));
0581         noopTest(QStringLiteral("insert02"));
0582         noopTest(QStringLiteral("insert03"));
0583     }
0584 
0585     void noop_testInsertInRootData()
0586     {
0587         QTest::addColumn<SignalList>("signalList");
0588         QTest::addColumn<PersistentChangeList>("changeList");
0589 
0590         // These commands have no effect because this model shows children of selection.
0591 
0592         noopTest(QStringLiteral("insert01"));
0593         noopTest(QStringLiteral("insert02"));
0594         noopTest(QStringLiteral("insert03"));
0595         noopTest(QStringLiteral("insert04"));
0596         noopTest(QStringLiteral("insert05"));
0597         noopTest(QStringLiteral("insert06"));
0598         noopTest(QStringLiteral("insert07"));
0599         noopTest(QStringLiteral("insert08"));
0600         noopTest(QStringLiteral("insert09"));
0601         noopTest(QStringLiteral("insert10"));
0602         noopTest(QStringLiteral("insert11"));
0603         noopTest(QStringLiteral("insert12"));
0604         noopTest(QStringLiteral("insert13"));
0605         noopTest(QStringLiteral("insert14"));
0606         noopTest(QStringLiteral("insert15"));
0607         noopTest(QStringLiteral("insert16"));
0608         noopTest(QStringLiteral("insert17"));
0609         noopTest(QStringLiteral("insert18"));
0610     }
0611 
0612     void noop_testInsertInTopLevelData()
0613     {
0614         // Same test names etc.
0615         noop_testInsertInRootData();
0616     }
0617 
0618     void noop_testInsertInSecondLevelData()
0619     {
0620         noop_testInsertInRootData();
0621     }
0622 
0623     void noop_testRemoveFromRootData()
0624     {
0625         QTest::addColumn<SignalList>("signalList");
0626         QTest::addColumn<PersistentChangeList>("changeList");
0627 
0628         // These commands have no effect because this model shows children of selection.
0629 
0630         noopTest(QStringLiteral("remove01"));
0631         noopTest(QStringLiteral("remove02"));
0632         noopTest(QStringLiteral("remove03"));
0633     }
0634 
0635     void noop_testRemoveFromTopLevelData()
0636     {
0637         // Same test names etc.
0638         noop_testRemoveFromRootData();
0639     }
0640 
0641     void noop_testRemoveFromSecondLevelData()
0642     {
0643         noop_testRemoveFromRootData();
0644     }
0645 
0646     void noop_testMoveFromRootData()
0647     {
0648         QTest::addColumn<SignalList>("signalList");
0649         QTest::addColumn<PersistentChangeList>("changeList");
0650 
0651         // These commands have no effect because this model shows children of selection.
0652 
0653         noopLayoutChangeTest(QStringLiteral("move01"));
0654         noopLayoutChangeTest(QStringLiteral("move02"));
0655         noopLayoutChangeTest(QStringLiteral("move03"));
0656         noopLayoutChangeTest(QStringLiteral("move04"));
0657         noopLayoutChangeTest(QStringLiteral("move05"));
0658     }
0659 
0660     void noop_testMoveFromTopLevelData()
0661     {
0662         // Same test names etc.
0663         noop_testMoveFromRootData();
0664     }
0665 
0666     void noop_testMoveFromSecondLevelData()
0667     {
0668         noop_testMoveFromRootData();
0669     }
0670 
0671     void noop_testModifyInRootData()
0672     {
0673         QTest::addColumn<SignalList>("signalList");
0674         QTest::addColumn<PersistentChangeList>("changeList");
0675 
0676         noopTest(QStringLiteral("modify01"));
0677         noopTest(QStringLiteral("modify02"));
0678         noopTest(QStringLiteral("modify03"));
0679         noopTest(QStringLiteral("modify04"));
0680         noopTest(QStringLiteral("modify05"));
0681         noopTest(QStringLiteral("modify06"));
0682         noopTest(QStringLiteral("modify07"));
0683     }
0684 
0685     void noop_testModifyInTopLevelData()
0686     {
0687         // Same test names etc.
0688         noop_testModifyInRootData();
0689     }
0690 
0691     void noop_testModifyInSecondLevelData()
0692     {
0693         noop_testModifyInRootData();
0694     }
0695 
0696     ProxyModelTest *m_proxyModelTest;
0697     QString m_currentTestFunction;
0698     QSet<QString> m_testNames;
0699 };
0700 
0701 PROXYMODELTESTSUITE_EXPORT uint qHash(const QVariant &var);
0702 
0703 /* clang-format off */
0704 #define PROXYMODELTEST(TestData, TemplateArg, IntermediateProxy, LazyPersistence, Config) \
0705     if (testObjects.isEmpty() || testObjects.contains(testNum)) { \
0706         proxyModelTestClass->setTestData(new TestData<TemplateArg>(proxyModelTestClass)); \
0707         proxyModelTestClass->setUseIntermediateProxy(IntermediateProxy); \
0708         proxyModelTestClass->setLazyPersistence(LazyPersistence); \
0709         qDebug() << "\n   Running" << proxyModelTestClass->objectName().toLatin1() << testNum << ":\n" \
0710                  << "  Source Model:      " << #IntermediateProxy << "\n" \
0711                  << "  Persistence:       " << #LazyPersistence << "\n" Config; \
0712         result = QTest::qExec(proxyModelTestClass, arguments); \
0713         if (result != 0) \
0714             return result; \
0715     } \
0716     ++testNum;
0717 
0718 #define PROXYMODELTEST_CUSTOM(TestData, IntermediateProxy, LazyPersistence, Config) \
0719     if (testObjects.isEmpty() || testObjects.contains(testNum)) { \
0720         proxyModelTestClass->setTestData(TestData); \
0721         proxyModelTestClass->setUseIntermediateProxy(IntermediateProxy); \
0722         proxyModelTestClass->setLazyPersistence(LazyPersistence); \
0723         qDebug() << "\n   Running" << proxyModelTestClass->objectName().toLatin1() << testNum << ":\n" \
0724                  << "  Source Model:      " << #IntermediateProxy << "\n" \
0725                  << "  Persistence:       " << #LazyPersistence << "\n" Config; \
0726         result = QTest::qExec(proxyModelTestClass, arguments); \
0727         if (result != 0) \
0728             return result; \
0729     } \
0730     ++testNum;
0731 
0732 // The DynamicTreeModel uses a unique internalId for the first column of each row.
0733 // In the QSortFilterProxyModel the internalId is shared between all rows of the same parent.
0734 // We test the proxy on top of both so that we know it is not using the internalId of its source model
0735 // which will be different each time the test is run.
0736 #define COMPLETETEST(TestData, TemplateArg, Config) \
0737     PROXYMODELTEST(TestData, TemplateArg, DynamicTree, ImmediatePersistence, Config) \
0738     PROXYMODELTEST(TestData, TemplateArg, IntermediateProxy, ImmediatePersistence, Config) \
0739     PROXYMODELTEST(TestData, TemplateArg, DynamicTree, LazyPersistence, Config) \
0740     PROXYMODELTEST(TestData, TemplateArg, IntermediateProxy, LazyPersistence, Config)
0741 
0742 #define PROXYMODELTEST_MAIN(TestClass, Body) \
0743     int main(int argc, char *argv[]) \
0744     { \
0745         QApplication app(argc, argv); \
0746         QList<int> testObjects; \
0747         QStringList arguments; \
0748         bool ok; \
0749         const auto lst = app.arguments(); \
0750         for (const QString &arg : lst) { \
0751             int testObject = arg.toInt(&ok); \
0752             if (arg == "-count") \
0753                 continue; \
0754             if (!ok) { \
0755                 arguments.append(arg); \
0756                 continue; \
0757             } \
0758             testObjects.append(testObject); \
0759         } \
0760         TestClass *proxyModelTestClass = new TestClass(); \
0761         proxyModelTestClass->setObjectName(#TestClass); \
0762         int result = 0; \
0763         int testNum = 1; \
0764         \
0765         Body \
0766         \
0767             delete proxyModelTestClass; \
0768         return result; \
0769     }
0770 
0771 /* clang-format on */
0772 #endif