File indexing completed on 2025-01-05 04:59:56

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org>
0003  SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 
0007 #include <testlib/qtest_zanshin.h>
0008 
0009 #include "domain/queryresult.h"
0010 
0011 using namespace Domain;
0012 
0013 class Base
0014 {
0015 public:
0016     typedef QSharedPointer<Base> Ptr;
0017 
0018     virtual ~Base() {}
0019     virtual QString whoAmI() { return QStringLiteral("I'm Base"); }
0020 };
0021 
0022 class Derived : public Base
0023 {
0024 public:
0025     typedef QSharedPointer<Derived> Ptr;
0026 
0027     QString whoAmI() override { return QStringLiteral("I'm Derived"); }
0028 };
0029 
0030 class QueryResultTest : public QObject
0031 {
0032     Q_OBJECT
0033 private slots:
0034     void shouldBeCreatedEmpty()
0035     {
0036         QueryResultProvider<QString>::Ptr provider(new QueryResultProvider<QString>);
0037         QVERIFY(provider->data().isEmpty());
0038 
0039         QueryResult<QString>::Ptr result = QueryResult<QString>::create(provider);
0040         QVERIFY(result->data().isEmpty());
0041     }
0042 
0043     void shouldHaveSameContent()
0044     {
0045         QueryResultProvider<QString>::Ptr provider(new QueryResultProvider<QString>);
0046         QueryResult<QString>::Ptr result = QueryResult<QString>::create(provider);
0047 
0048         provider->append(QStringLiteral("Bar"));
0049 
0050         QVERIFY(!provider->data().isEmpty());
0051         QVERIFY(!result->data().isEmpty());
0052 
0053         QCOMPARE(provider->data().size(), 1);
0054         QCOMPARE(result->data().size(), 1);
0055         QCOMPARE(provider->data().first(), QStringLiteral("Bar"));
0056         QCOMPARE(result->data().first(), QStringLiteral("Bar"));
0057 
0058         provider->prepend(QStringLiteral("Foo"));
0059         *provider << QStringLiteral("Baz");
0060 
0061         QCOMPARE(provider->data().size(), 3);
0062         QCOMPARE(result->data().size(), 3);
0063         QCOMPARE(provider->data().first(), QStringLiteral("Foo"));
0064         QCOMPARE(result->data().first(), QStringLiteral("Foo"));
0065         QCOMPARE(provider->data().at(1), QStringLiteral("Bar"));
0066         QCOMPARE(result->data().at(1), QStringLiteral("Bar"));
0067         QCOMPARE(provider->data().last(), QStringLiteral("Baz"));
0068         QCOMPARE(result->data().last(), QStringLiteral("Baz"));
0069     }
0070 
0071     void shouldCreateResultFromAnotherResultOfSameType()
0072     {
0073         auto provider = QueryResultProvider<QString>::Ptr::create();
0074         auto result = QueryResult<QString>::create(provider);
0075 
0076         provider->append(QStringLiteral("Foo"));
0077         provider->append(QStringLiteral("Bar"));
0078         provider->append(QStringLiteral("Baz"));
0079 
0080         QVERIFY(!provider->data().isEmpty());
0081         QVERIFY(!result->data().isEmpty());
0082         QCOMPARE(result->data(), provider->data());
0083 
0084         auto otherResult = QueryResult<QString>::copy(result);
0085         QCOMPARE(otherResult->data(), result->data());
0086     }
0087 
0088     void shouldCreateResultFromAnotherResultOfCompatibleType()
0089     {
0090         auto provider = QueryResultProvider<Derived::Ptr>::Ptr::create();
0091         auto result = QueryResult<Derived::Ptr>::create(provider);
0092 
0093         provider->append(Derived::Ptr::create());
0094 
0095         QList<Base::Ptr> baseList;
0096         baseList << provider->data().first();
0097 
0098         QVERIFY(!provider->data().isEmpty());
0099         QVERIFY(!result->data().isEmpty());
0100         QCOMPARE(result->data(), provider->data());
0101 
0102         auto otherResult = QueryResult<Derived::Ptr, Base::Ptr>::copy(result);
0103         QCOMPARE(otherResult->data(), baseList);
0104     }
0105 
0106     void shouldProperlyCopyNullPointers()
0107     {
0108         QueryResult<QString>::Ptr result;
0109         QVERIFY(QueryResult<QString>::copy(result).isNull());
0110     }
0111 
0112     void shouldResultsKeepProviderAlive()
0113     {
0114         QueryResultProvider<QString>::WeakPtr provider;
0115         QVERIFY(provider.isNull());
0116 
0117         {
0118             QueryResult<QString>::Ptr result1;
0119 
0120             {
0121                 QueryResultProvider<QString>::Ptr strongProvider(new QueryResultProvider<QString>);
0122                 provider = strongProvider;
0123                 QVERIFY(!provider.isNull());
0124                 result1 = QueryResult<QString>::create(provider.toStrongRef());
0125             }
0126             QVERIFY(!provider.isNull());
0127 
0128             {
0129                 QueryResult<QString>::Ptr result2 = QueryResult<QString>::create(provider.toStrongRef());
0130                 Q_UNUSED(result2);
0131                 QVERIFY(!provider.isNull());
0132             }
0133             QVERIFY(!provider.isNull());
0134         }
0135         QVERIFY(provider.isNull());
0136     }
0137 
0138     void shouldNotifyInserts()
0139     {
0140         QList<QString> preInserts, postInserts;
0141         QList<int> preInsertsPos, postInsertsPos;
0142 
0143         QueryResultProvider<QString>::Ptr provider(new QueryResultProvider<QString>);
0144         QueryResult<QString>::Ptr result = QueryResult<QString>::create(provider);
0145 
0146         result->addPreInsertHandler(
0147             [&](const QString &value, int pos)
0148             {
0149                 preInserts << value;
0150                 preInsertsPos << pos;
0151             }
0152         );
0153 
0154         result->addPostInsertHandler(
0155             [&](const QString &value, int pos)
0156             {
0157                 postInserts << value;
0158                 postInsertsPos << pos;
0159             }
0160         );
0161 
0162         provider->append(QStringLiteral("Bar"));
0163         provider->prepend(QStringLiteral("Foo"));
0164         *provider << QStringLiteral("Baz");
0165         provider->insert(1, QStringLiteral("Bazz"));
0166 
0167         const QList<QString> expectedInserts = {"Bar", "Foo", "Baz", "Bazz"};
0168         const QList<int> expectedInsertsPos = {0, 0, 2, 1};
0169         QCOMPARE(preInserts, expectedInserts);
0170         QCOMPARE(preInsertsPos, expectedInsertsPos);
0171         QCOMPARE(postInserts, expectedInserts);
0172         QCOMPARE(postInsertsPos, expectedInsertsPos);
0173     }
0174 
0175     void shouldNotifyInsertsForCompatibleTypes()
0176     {
0177         QList<Base::Ptr> preInserts, postInserts;
0178         QList<int> preInsertsPos, postInsertsPos;
0179 
0180         auto provider = QueryResultProvider<Derived::Ptr>::Ptr::create();
0181         auto derivedResult = QueryResult<Derived::Ptr>::create(provider);
0182         auto baseResult = QueryResult<Derived::Ptr, Base::Ptr>::copy(derivedResult);
0183 
0184         baseResult->addPreInsertHandler(
0185             [&](const Base::Ptr &value, int pos)
0186             {
0187                 preInserts << value;
0188                 preInsertsPos << pos;
0189             }
0190         );
0191 
0192         baseResult->addPostInsertHandler(
0193             [&](const Base::Ptr &value, int pos)
0194             {
0195                 postInserts << value;
0196                 postInsertsPos << pos;
0197             }
0198         );
0199 
0200         provider->append(Derived::Ptr::create());
0201         provider->append(Derived::Ptr::create());
0202 
0203         const QList<Base::Ptr> expectedInserts = { provider->data().first(), provider->data().last() };
0204         const QList<int> expectedInsertsPos = {0, 1};
0205         QCOMPARE(preInserts, expectedInserts);
0206         QCOMPARE(preInsertsPos, expectedInsertsPos);
0207         QCOMPARE(postInserts, expectedInserts);
0208         QCOMPARE(postInsertsPos, expectedInsertsPos);
0209     }
0210 
0211     void shouldNotifyRemoves()
0212     {
0213         QList<QString> preRemoves, postRemoves;
0214         QList<int> preRemovesPos, postRemovesPos;
0215 
0216         QueryResultProvider<QString>::Ptr provider(new QueryResultProvider<QString>);
0217         *provider << QStringLiteral("Foo") << QStringLiteral("Bar") << QStringLiteral("Baz") << QStringLiteral("Bazz");
0218 
0219         QueryResult<QString>::Ptr result = QueryResult<QString>::create(provider);
0220 
0221         result->addPreRemoveHandler(
0222             [&](const QString &value, int pos)
0223             {
0224                 preRemoves << value;
0225                 preRemovesPos << pos;
0226             }
0227         );
0228 
0229         result->addPostRemoveHandler(
0230             [&](const QString &value, int pos)
0231             {
0232                 postRemoves << value;
0233                 postRemovesPos << pos;
0234             }
0235         );
0236 
0237         provider->removeAt(1);
0238         provider->removeFirst();
0239         provider->removeLast();
0240 
0241         const QList<QString> expectedRemoves = {"Bar", "Foo", "Bazz"};
0242         const QList<int> expectedRemovesPos = {1, 0, 1};
0243         QCOMPARE(preRemoves, expectedRemoves);
0244         QCOMPARE(preRemovesPos, expectedRemovesPos);
0245         QCOMPARE(postRemoves, expectedRemoves);
0246         QCOMPARE(postRemovesPos, expectedRemovesPos);
0247     }
0248 
0249     void shouldNotifyTakes()
0250     {
0251         QList<QString> preRemoves, postRemoves, taken;
0252         QList<int> preRemovesPos, postRemovesPos;
0253 
0254         QueryResultProvider<QString>::Ptr provider(new QueryResultProvider<QString>);
0255         *provider << QStringLiteral("Foo") << QStringLiteral("Bar") << QStringLiteral("Baz") << QStringLiteral("Bazz");
0256 
0257         QueryResult<QString>::Ptr result = QueryResult<QString>::create(provider);
0258 
0259         result->addPreRemoveHandler(
0260             [&](const QString &value, int pos)
0261             {
0262                 preRemoves << value;
0263                 preRemovesPos << pos;
0264             }
0265         );
0266 
0267         result->addPostRemoveHandler(
0268             [&](const QString &value, int pos)
0269             {
0270                 postRemoves << value;
0271                 postRemovesPos << pos;
0272             }
0273         );
0274 
0275         taken << provider->takeAt(1);
0276         taken << provider->takeFirst();
0277         taken << provider->takeLast();
0278 
0279         const QList<QString> expectedRemoves = {"Bar", "Foo", "Bazz"};
0280         const QList<int> expectedRemovesPos = {1, 0, 1};
0281         QCOMPARE(preRemoves, expectedRemoves);
0282         QCOMPARE(preRemovesPos, expectedRemovesPos);
0283         QCOMPARE(postRemoves, expectedRemoves);
0284         QCOMPARE(postRemovesPos, expectedRemovesPos);
0285         QCOMPARE(taken, expectedRemoves);
0286     }
0287 
0288     void shouldNotifyReplaces()
0289     {
0290         QList<QString> preReplaces, postReplaces;
0291         QList<int> preReplacesPos, postReplacesPos;
0292 
0293         QueryResultProvider<QString>::Ptr provider(new QueryResultProvider<QString>);
0294         *provider << QStringLiteral("Foo") << QStringLiteral("Foo") << QStringLiteral("Foo") << QStringLiteral("Foo");
0295 
0296         QueryResult<QString>::Ptr result = QueryResult<QString>::create(provider);
0297 
0298         result->addPreReplaceHandler(
0299             [&](const QString &value, int pos)
0300             {
0301                 preReplaces << value;
0302                 preReplacesPos << pos;
0303             }
0304         );
0305 
0306         result->addPostReplaceHandler(
0307             [&](const QString &value, int pos)
0308             {
0309                 postReplaces << value;
0310                 postReplacesPos << pos;
0311             }
0312         );
0313 
0314         provider->replace(1, QStringLiteral("Bar"));
0315         provider->replace(2, QStringLiteral("Baz"));
0316 
0317         const QList<QString> expectedPreReplaces = {"Foo", "Foo"};
0318         const QList<QString> expectedPostReplaces = {"Bar", "Baz"};
0319         const QList<int> expectedReplacesPos = {1, 2};
0320         QCOMPARE(preReplaces, expectedPreReplaces);
0321         QCOMPARE(preReplacesPos, expectedReplacesPos);
0322         QCOMPARE(postReplaces, expectedPostReplaces);
0323         QCOMPARE(postReplacesPos, expectedReplacesPos);
0324     }
0325 };
0326 
0327 ZANSHIN_TEST_MAIN(QueryResultTest)
0328 
0329 #include "queryresulttest.moc"