File indexing completed on 2024-05-19 16:38:19

0001 /*
0002     SPDX-FileCopyrightText: 2015 Ivan Cukic <ivan.cukic(at)kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "ResultSetQuickCheckTest.h"
0008 
0009 #include <QCoreApplication>
0010 #include <QDBusConnection>
0011 #include <QDBusConnectionInterface>
0012 #include <QDebug>
0013 #include <QRandomGenerator>
0014 #include <QString>
0015 #include <QTemporaryDir>
0016 #include <QTest>
0017 #include <QUuid>
0018 
0019 #include <boost/range/adaptor/filtered.hpp>
0020 #include <boost/range/algorithm.hpp>
0021 #include <boost/range/algorithm/sort.hpp>
0022 #include <boost/range/numeric.hpp>
0023 
0024 #include <query.h>
0025 #include <resultset.h>
0026 
0027 #include <iostream>
0028 
0029 #include <common/database/Database.h>
0030 #include <common/database/schema/ResourcesDatabaseSchema.h>
0031 
0032 #include <utils/qsqlquery_iterator.h>
0033 
0034 #define NUMBER_ACTIVITIES 10
0035 #define NUMBER_AGENTS 10
0036 #define NUMBER_RESOURCES 50
0037 #define NUMBER_CACHES 200
0038 
0039 namespace KAStats = KActivities::Stats;
0040 
0041 static ResultSetQuickCheckTest *instance;
0042 
0043 ResultSetQuickCheckTest::ResultSetQuickCheckTest(QObject *parent)
0044     : Test(parent)
0045     , activities(std::make_unique<KActivities::Consumer>())
0046 {
0047     instance = this;
0048 }
0049 
0050 namespace
0051 {
0052 QString resourceTitle(const QString &resource)
0053 {
0054     // We need to find the title
0055     ResourceInfo::Item key;
0056     key.targettedResource = resource;
0057 
0058     auto &infos = instance->resourceInfos;
0059 
0060     auto ri = infos.lower_bound(key);
0061 
0062     return (ri != infos.cend() && ri->targettedResource == resource) ? ri->title : resource;
0063 }
0064 
0065 QString toQString(const ResourceScoreCache::Item &item)
0066 {
0067     /* clang-format off */
0068     return
0069         item.targettedResource
0070         + QLatin1Char(':') + resourceTitle(item.targettedResource)
0071         + QLatin1Char('(') + QString::number(item.cachedScore) + QLatin1Char(')');
0072     /* clang-format on */
0073 }
0074 
0075 QString toQString(const ResourceLink::Item &item)
0076 {
0077     return item.targettedResource + QLatin1Char(':') + resourceTitle(item.targettedResource);
0078     // + '(' + QString::number(0/* item.score */) + ')'
0079 }
0080 
0081 QString toQString(const KAStats::ResultSet::Result &item)
0082 {
0083     /* clang-format off */
0084     return
0085         item.resource()
0086         + QLatin1Char(':') + item.title()
0087         + QLatin1Char('(') + QString::number(item.score()) + QLatin1Char(')');
0088     /* clang-format on */
0089 }
0090 
0091 bool operator==(const ResourceScoreCache::Item &left, const KAStats::ResultSet::Result &right)
0092 {
0093     /* clang-format off */
0094     return left.targettedResource == right.resource()
0095         && resourceTitle(left.targettedResource) == right.title()
0096         && qFuzzyCompare(left.cachedScore, right.score());
0097     /* clang-format on */
0098 }
0099 
0100 bool operator==(const ResourceLink::Item &left, const KAStats::ResultSet::Result &right)
0101 {
0102     return left.targettedResource == right.resource() //
0103         && resourceTitle(left.targettedResource) == right.title();
0104     // && qFuzzyCompare(left.cachedScore, right.score);
0105 }
0106 
0107 template<typename Left>
0108 void assert_range_equal(const Left &left, const KAStats::ResultSet &right, const char *file, int line)
0109 {
0110     auto leftIt = left.cbegin();
0111     auto rightIt = right.cbegin();
0112     auto leftEnd = left.cend();
0113     auto rightEnd = right.cend();
0114 
0115     bool equal = true;
0116 
0117     QString leftLine;
0118     QString rightLine;
0119 
0120     for (; leftIt != leftEnd && rightIt != rightEnd; ++leftIt, ++rightIt) {
0121         auto leftString = toQString(*leftIt);
0122         auto rightString = toQString(*rightIt);
0123 
0124         if (*leftIt == *rightIt) {
0125             rightString.fill(QLatin1Char('.'));
0126 
0127         } else {
0128             equal = false;
0129         }
0130 
0131         int longer = qMax(leftString.length(), rightString.length());
0132         leftString = leftString.leftJustified(longer);
0133         rightString = rightString.leftJustified(longer, QLatin1Char('.'));
0134 
0135         leftLine += QStringLiteral(" ") + leftString;
0136         rightLine += QStringLiteral(" ") + rightString;
0137     }
0138 
0139     // So far, we are equal, but do we have the same number
0140     // of elements - did we reach the end of both ranges?
0141     if (leftIt != leftEnd) {
0142         for (; leftIt != leftEnd; ++leftIt) {
0143             auto item = toQString(*leftIt);
0144             leftLine += QStringLiteral(" ") + item;
0145             item.fill(QLatin1Char('X'));
0146             rightLine += QStringLiteral(" ") + item;
0147         }
0148         equal = false;
0149 
0150     } else if (rightIt != rightEnd) {
0151         for (; rightIt != rightEnd; ++rightIt) {
0152             auto item = toQString(*leftIt);
0153             rightLine += QStringLiteral(" ") + item;
0154             item.fill(QLatin1Char('X'));
0155             leftLine += QStringLiteral(" ") + item;
0156         }
0157         equal = false;
0158     }
0159 
0160     if (!equal) {
0161         qDebug() << "Ranges differ:\n"
0162                  << "MEM: " << leftLine << '\n'
0163                  << "SQL: " << rightLine;
0164         QTest::qFail("Results do not match", file, line);
0165     }
0166 }
0167 
0168 #define ASSERT_RANGE_EQUAL(L, R) assert_range_equal(L, R, __FILE__, __LINE__)
0169 }
0170 
0171 //_ Data init
0172 void ResultSetQuickCheckTest::initTestCase()
0173 {
0174     QString databaseFile;
0175 
0176     int dbArgIndex = QCoreApplication::arguments().indexOf(QStringLiteral("--ResultSetQuickCheckDatabase"));
0177     if (dbArgIndex > 0) {
0178         databaseFile = QCoreApplication::arguments()[dbArgIndex + 1];
0179 
0180         qDebug() << "Using an existing database: " << databaseFile;
0181         Common::ResourcesDatabaseSchema::overridePath(databaseFile);
0182 
0183         pullFromDatabase();
0184 
0185     } else {
0186         QTemporaryDir dir(QDir::tempPath() + QStringLiteral("/KActivitiesStatsTest_ResultSetQuickCheckTest_XXXXXX"));
0187         dir.setAutoRemove(false);
0188 
0189         if (!dir.isValid()) {
0190             qFatal("Can not create a temporary directory");
0191         }
0192 
0193         databaseFile = dir.path() + QStringLiteral("/database");
0194 
0195         qDebug() << "Creating database in " << databaseFile;
0196         Common::ResourcesDatabaseSchema::overridePath(databaseFile);
0197 
0198         while (activities->serviceStatus() == KActivities::Consumer::Unknown) {
0199             QCoreApplication::processEvents();
0200         }
0201 
0202         generateActivitiesList();
0203         generateAgentsList();
0204         generateTypesList();
0205         generateResourcesList();
0206 
0207         generateResourceInfos();
0208         generateResourceScoreCaches();
0209         generateResourceLinks();
0210 
0211         pushToDatabase();
0212     }
0213 
0214     if (QCoreApplication::arguments().contains(QLatin1String("--show-data"))) {
0215         QString rscs;
0216         for (const auto &rsc : resourceScoreCaches) {
0217             /* clang-format off */
0218             rscs += QLatin1Char('(') + rsc.targettedResource
0219                     + QLatin1Char(',') + rsc.usedActivity
0220                     + QLatin1Char(',') + rsc.initiatingAgent
0221                     + QLatin1Char(',') + QString::number(rsc.cachedScore) + QLatin1Char(')');
0222             /* clang-format on */
0223         }
0224 
0225         QString ris;
0226         for (const auto &ri : resourceInfos) {
0227             /* clang-format off */
0228             ris += QLatin1Char('(') + ri.targettedResource
0229                    + QLatin1Char(',') + ri.title
0230                    + QLatin1Char(',') + ri.mimetype + QLatin1Char(')');
0231             /* clang-format on*/
0232         }
0233 
0234         QString rls;
0235         for (const auto &rl : resourceLinks) {
0236             /* clang-format off */
0237             rls += QLatin1Char('(') + rl.targettedResource
0238                    + QLatin1Char(',') + rl.usedActivity
0239                    + QLatin1Char(',') + rl.initiatingAgent + QLatin1Char(')');
0240             /* clang-format on */
0241         }
0242 
0243         /* clang-format off */
0244         qDebug() << "\nUsed data: -----------------------------"
0245                  << "\nActivities: " << activitiesList
0246                  << "\nAgents: " << agentsList
0247                  << "\nTypes: " << typesList
0248                  << "\nResources: " << resourcesList
0249                  << "\n----------------------------------------";
0250         qDebug() << "\n RSCs: " << rscs;
0251         qDebug() << "\n RIs:  " << ris;
0252         qDebug() << "\n RLs:  " << rls
0253                  << "\n----------------------------------------";
0254         /* clang-format on */
0255     }
0256 }
0257 
0258 void ResultSetQuickCheckTest::generateActivitiesList()
0259 {
0260     activitiesList = activities->activities();
0261 
0262     while (activitiesList.size() < NUMBER_ACTIVITIES) {
0263         activitiesList << QUuid::createUuid().toString().mid(1, 36);
0264     }
0265 }
0266 
0267 void ResultSetQuickCheckTest::generateAgentsList()
0268 {
0269     for (int i = 0; i < NUMBER_AGENTS; ++i) {
0270         agentsList << QStringLiteral("Agent_") + QString::number(i);
0271     }
0272 }
0273 
0274 void ResultSetQuickCheckTest::generateTypesList()
0275 {
0276     /* clang-format off */
0277     typesList
0278         << QStringLiteral("application/postscript")
0279         << QStringLiteral("application/pdf")
0280         << QStringLiteral("image/x-psd")
0281         << QStringLiteral("image/x-sgi")
0282         << QStringLiteral("image/x-tga")
0283         << QStringLiteral("image/x-xbitmap")
0284         << QStringLiteral("image/x-xwindowdump")
0285         << QStringLiteral("image/x-xcf")
0286         << QStringLiteral("image/x-compressed-xcf")
0287         << QStringLiteral("image/tiff")
0288         << QStringLiteral("image/jpeg")
0289         << QStringLiteral("image/x-psp")
0290         << QStringLiteral("image/png")
0291         << QStringLiteral("image/x-icon")
0292         << QStringLiteral("image/x-xpixmap")
0293         << QStringLiteral("image/svg+xml")
0294         << QStringLiteral("application/pdf")
0295         << QStringLiteral("image/x-wmf")
0296         << QStringLiteral("image/jp2")
0297         << QStringLiteral("image/jpeg2000")
0298         << QStringLiteral("image/jpx")
0299         << QStringLiteral("image/x-xcursor");
0300     /* clang-format on */
0301 }
0302 
0303 void ResultSetQuickCheckTest::generateResourcesList()
0304 {
0305     for (int i = 0; i < NUMBER_RESOURCES; ++i) {
0306         resourcesList << (QStringLiteral("/r") //
0307                           + (i < 10 ? QStringLiteral("0") : QString()) + QString::number(i));
0308     }
0309 }
0310 
0311 void ResultSetQuickCheckTest::generateResourceInfos()
0312 {
0313     auto *generator = QRandomGenerator::global();
0314     for (const QString &resource : std::as_const(resourcesList)) {
0315         // We want every n-th or so to be without the title
0316         if (generator->bounded(3)) {
0317             continue;
0318         }
0319 
0320         ResourceInfo::Item ri;
0321         ri.targettedResource = resource;
0322         ri.title = QStringLiteral("Title_") + QString::number(generator->bounded(100));
0323         ri.mimetype = randItem(typesList);
0324 
0325         resourceInfos.insert(ri);
0326     }
0327 }
0328 
0329 void ResultSetQuickCheckTest::generateResourceScoreCaches()
0330 {
0331     auto *generator = QRandomGenerator::global();
0332     for (int i = 0; i < NUMBER_CACHES; ++i) {
0333         ResourceScoreCache::Item rsc;
0334 
0335         rsc.usedActivity = randItem(activitiesList);
0336         rsc.initiatingAgent = randItem(agentsList);
0337         rsc.targettedResource = randItem(resourcesList);
0338 
0339         rsc.cachedScore = generator->bounded(1000);
0340         rsc.firstUpdate = generator->generate();
0341         rsc.lastUpdate = generator->generate();
0342 
0343         resourceScoreCaches.insert(rsc);
0344     }
0345 }
0346 
0347 void ResultSetQuickCheckTest::generateResourceLinks()
0348 {
0349     auto *generator = QRandomGenerator::global();
0350     for (const QString &resource : std::as_const(resourcesList)) {
0351         // We don't want all the resources to be linked
0352         // to something
0353         if (generator->bounded(2)) {
0354             continue;
0355         }
0356 
0357         ResourceLink::Item rl;
0358 
0359         rl.targettedResource = resource;
0360         rl.usedActivity = randItem(activitiesList);
0361         rl.initiatingAgent = randItem(agentsList);
0362 
0363         resourceLinks.insert(rl);
0364     }
0365 }
0366 
0367 void ResultSetQuickCheckTest::pushToDatabase()
0368 {
0369     auto database = Common::Database::instance(Common::Database::ResourcesDatabase, Common::Database::ReadWrite);
0370 
0371     Common::ResourcesDatabaseSchema::initSchema(*database);
0372 
0373     // Inserting activities, so that a test can be replicated
0374     database->execQuery(QStringLiteral("CREATE TABLE Activity (activity TEXT)"));
0375     for (const auto &activity : activitiesList) {
0376         database->execQuery(QStringLiteral("INSERT INTO Activity VALUES ('%1')").arg(activity));
0377     }
0378 
0379     // Inserting agent, so that a test can be replicated
0380     database->execQuery(QStringLiteral("CREATE TABLE Agent (agent TEXT)"));
0381     for (const auto &agent : agentsList) {
0382         database->execQuery(QStringLiteral("INSERT INTO Agent VALUES ('%1')").arg(agent));
0383     }
0384 
0385     // Inserting types, so that a test can be replicated
0386     database->execQuery(QStringLiteral("CREATE TABLE Type (type TEXT)"));
0387     for (const auto &type : typesList) {
0388         database->execQuery(QStringLiteral("INSERT INTO Type VALUES ('%1')").arg(type));
0389     }
0390 
0391     // Inserting resources, so that a test can be replicated
0392     database->execQuery(QStringLiteral("CREATE TABLE Resource (resource TEXT)"));
0393     for (const auto &resource : resourcesList) {
0394         database->execQuery(QStringLiteral("INSERT INTO Resource VALUES ('%1')").arg(resource));
0395     }
0396 
0397     // Inserting resource score caches
0398     qDebug() << "Inserting" << resourceScoreCaches.size() << "items into ResourceScoreCache";
0399     int i = 0;
0400 
0401     for (const auto &rsc : std::as_const(resourceScoreCaches)) {
0402         std::cerr << '.';
0403 
0404         if (++i % 10 == 0) {
0405             std::cerr << i;
0406         }
0407 
0408         /* clang-format off */
0409         database->execQuery(QStringLiteral(
0410             "INSERT INTO ResourceScoreCache ("
0411                 "  usedActivity"
0412                 ", initiatingAgent"
0413                 ", targettedResource"
0414                 ", scoreType"
0415                 ", cachedScore"
0416                 ", firstUpdate"
0417                 ", lastUpdate"
0418             ") VALUES ("
0419                 "  '%1'" // usedActivity
0420                 ", '%2'" // initiatingAgent
0421                 ", '%3'" // targettedResource
0422                 ",   0 " // scoreType
0423                 ",  %4 " // cachedScore
0424                 ",  %5 " // firstUpdate
0425                 ",  %6 " // lastUpdate
0426             ")"
0427         )
0428             .arg(rsc.usedActivity)
0429             .arg(rsc.initiatingAgent)
0430             .arg(rsc.targettedResource)
0431             .arg(rsc.cachedScore)
0432             .arg(rsc.firstUpdate)
0433             .arg(rsc.lastUpdate)
0434         );
0435         /* clang-format on */
0436 
0437     }
0438     std::cerr << std::endl;
0439 
0440     // Inserting resource infos
0441     qDebug() << "Inserting" << resourceInfos.size() << "items into ResourceInfo";
0442     i = 0;
0443 
0444     for (const auto &ri : std::as_const(resourceInfos)) {
0445         std::cerr << '.';
0446 
0447         if (++i % 10 == 0) {
0448             std::cerr << i;
0449         }
0450 
0451         /* clang-format off */
0452         database->execQuery(QStringLiteral(
0453             "INSERT INTO ResourceInfo ("
0454                 "  targettedResource"
0455                 ", title"
0456                 ", mimetype"
0457                 ", autoTitle"
0458                 ", autoMimetype"
0459             ") VALUES ("
0460                 "  '%1' " // targettedResource
0461                 ", '%2' " // title
0462                 ", '%3' " // mimetype
0463                 ",   1  " // autoTitle
0464                 ",   1  " // autoMimetype
0465             ")"
0466         )
0467             .arg(ri.targettedResource)
0468             .arg(ri.title)
0469             .arg(ri.mimetype)
0470         );
0471         /* clang-format on */
0472     }
0473     std::cerr << std::endl;
0474 
0475     // Inserting resource links
0476     qDebug() << "Inserting" << resourceLinks.size() << "items into ResourceLink";
0477     i = 0;
0478 
0479     for (const auto &rl : std::as_const(resourceLinks)) {
0480         std::cerr << '.';
0481 
0482         if (++i % 10 == 0) {
0483             std::cerr << i;
0484         }
0485 
0486         /* clang-format off */
0487         database->execQuery(QStringLiteral(
0488             "INSERT INTO ResourceLink ("
0489                 "  targettedResource"
0490                 ", usedActivity"
0491                 ", initiatingAgent"
0492             ") VALUES ("
0493                 "  '%1' " // targettedResource
0494                 ", '%2' " // usedActivity
0495                 ", '%3' " // initiatingAgent
0496             ")"
0497         )
0498             .arg(rl.targettedResource)
0499             .arg(rl.usedActivity)
0500             .arg(rl.initiatingAgent)
0501         );
0502         /* clang-format on */
0503 
0504     }
0505     std::cerr << std::endl;
0506 }
0507 
0508 void ResultSetQuickCheckTest::pullFromDatabase()
0509 {
0510     auto database = Common::Database::instance(Common::Database::ResourcesDatabase, Common::Database::ReadWrite);
0511 
0512     auto activityQuery = database->execQuery(QStringLiteral("SELECT * FROM Activity"));
0513     for (const auto &activity : activityQuery) {
0514         activitiesList << activity[0].toString();
0515     }
0516 
0517     auto agentQuery = database->execQuery(QStringLiteral("SELECT * FROM Agent"));
0518     for (const auto &agent : agentQuery) {
0519         agentsList << agent[0].toString();
0520     }
0521 
0522     auto typeQuery = database->execQuery(QStringLiteral("SELECT * FROM Type"));
0523     for (const auto &type : typeQuery) {
0524         typesList << type[0].toString();
0525     }
0526 
0527     auto resourceQuery = database->execQuery(QStringLiteral("SELECT * FROM Resource"));
0528     for (const auto &resource : resourceQuery) {
0529         resourcesList << resource[0].toString();
0530     }
0531 
0532     auto rscQuery = database->execQuery(QStringLiteral("SELECT * FROM ResourceScoreCache"));
0533 
0534     for (const auto &rsc : rscQuery) {
0535         ResourceScoreCache::Item item;
0536         item.usedActivity = rsc[QStringLiteral("usedActivity")].toString();
0537         item.initiatingAgent = rsc[QStringLiteral("initiatingAgent")].toString();
0538         item.targettedResource = rsc[QStringLiteral("targettedResource")].toString();
0539         item.cachedScore = rsc[QStringLiteral("cachedScore")].toDouble();
0540         item.firstUpdate = rsc[QStringLiteral("firstUpdate")].toInt();
0541         item.lastUpdate = rsc[QStringLiteral("lastUpdate")].toInt();
0542         resourceScoreCaches.insert(item);
0543     }
0544 
0545     auto riQuery = database->execQuery(QStringLiteral("SELECT * FROM ResourceInfo"));
0546 
0547     for (const auto &ri : riQuery) {
0548         ResourceInfo::Item item;
0549         item.targettedResource = ri[QStringLiteral("targettedResource")].toString();
0550         item.title = ri[QStringLiteral("title")].toString();
0551         item.mimetype = ri[QStringLiteral("mimetype")].toString();
0552         resourceInfos.insert(item);
0553     }
0554 
0555     auto rlQuery = database->execQuery(QStringLiteral("SELECT * FROM ResourceLink"));
0556 
0557     for (const auto &rl : rlQuery) {
0558         ResourceLink::Item item;
0559         item.targettedResource = rl[QStringLiteral("targettedResource")].toString();
0560         item.usedActivity = rl[QStringLiteral("usedActivity")].toString();
0561         item.initiatingAgent = rl[QStringLiteral("initiatingAgent")].toString();
0562         resourceLinks.insert(item);
0563     }
0564 }
0565 
0566 void ResultSetQuickCheckTest::cleanupTestCase()
0567 {
0568     Q_EMIT testFinished();
0569 }
0570 
0571 QString ResultSetQuickCheckTest::randItem(const QStringList &choices) const
0572 {
0573     return choices[QRandomGenerator::global()->bounded(choices.size())];
0574 }
0575 //^ Data init
0576 
0577 void ResultSetQuickCheckTest::testUsedResourcesForAgents()
0578 {
0579     using namespace KAStats;
0580     using namespace KAStats::Terms;
0581     using boost::sort;
0582     using boost::adaptors::filtered;
0583 
0584     for (const auto &agent : std::as_const(agentsList)) {
0585         auto memItems = ResourceScoreCache::groupByResource(resourceScoreCaches | filtered(ResourceScoreCache::initiatingAgent() == agent));
0586 
0587         auto baseTerm = UsedResources | Agent{agent} | Activity::any();
0588 
0589 #define ORDERING_TEST(Column, Dir, OrderFlag)                                                                                                                  \
0590     {                                                                                                                                                          \
0591         sort(memItems, ResourceScoreCache::Column().Dir() | ResourceScoreCache::targettedResource().asc());                                                    \
0592         ResultSet dbItems = baseTerm | OrderFlag | Limit(100);                                                                                                 \
0593         ASSERT_RANGE_EQUAL(memItems, dbItems);                                                                                                                 \
0594     }
0595 
0596         ORDERING_TEST(targettedResource, asc, OrderByUrl)
0597         ORDERING_TEST(cachedScore, desc, HighScoredFirst);
0598         ORDERING_TEST(lastUpdate, desc, RecentlyUsedFirst);
0599         ORDERING_TEST(firstUpdate, desc, RecentlyCreatedFirst);
0600 
0601 #undef ORDERING_TEST
0602     }
0603 }
0604 
0605 void ResultSetQuickCheckTest::testUsedResourcesForActivities()
0606 {
0607 }
0608 
0609 void ResultSetQuickCheckTest::testLinkedResourcesForAgents()
0610 {
0611     using namespace KAStats;
0612     using namespace KAStats::Terms;
0613     using boost::sort;
0614     using boost::adaptors::filtered;
0615 
0616     for (const auto &agent : std::as_const(agentsList)) {
0617         /* clang-format off */
0618         auto memItems = ResourceLink::groupByResource(
0619                 resourceLinks
0620                 | filtered(ResourceLink::initiatingAgent() == agent)
0621             );
0622 
0623         auto baseTerm = LinkedResources | Agent{agent} | Activity::any();
0624 
0625         #define ORDERING_TEST(Column, Dir, OrderFlag)                          \
0626         {                                                                      \
0627             sort(memItems, ResourceLink::Column().Dir()                        \
0628                            | ResourceLink::targettedResource().asc());         \
0629             ResultSet dbItems = baseTerm | OrderFlag;                          \
0630             ASSERT_RANGE_EQUAL(memItems, dbItems);                             \
0631         }
0632 
0633         ORDERING_TEST(targettedResource, asc,  OrderByUrl)
0634         // ORDERING_TEST(cachedScore,       desc, HighScoredFirst);
0635         // ORDERING_TEST(lastUpdate,        desc, RecentlyUsedFirst);
0636         // ORDERING_TEST(firstUpdate,       desc, RecentlyCreatedFirst);
0637 
0638         #undef ORDERING_TEST
0639 
0640         /* clang-format on */
0641     }
0642 
0643 }
0644 
0645 #include "moc_ResultSetQuickCheckTest.cpp"
0646 
0647 // vim: set foldmethod=marker: