File indexing completed on 2024-12-22 05:06:07

0001 /*
0002  *   Copyright (C) 2018 Christian Mollekopf <mollekopf@kolabsys.com>
0003  *
0004  *   This program is free software; you can redistribute it and/or modify
0005  *   it under the terms of the GNU General Public License as published by
0006  *   the Free Software Foundation; either version 2 of the License, or
0007  *   (at your option) any later version.
0008  *
0009  *   This program is distributed in the hope that it will be useful,
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *   GNU General Public License for more details.
0013  *
0014  *   You should have received a copy of the GNU General Public License
0015  *   along with this program; if not, write to the
0016  *   Free Software Foundation, Inc.,
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
0018  */
0019 
0020 #include <QCoreApplication>
0021 #include <QDebug>
0022 #include <QObject> // tr()
0023 #include <QModelIndex>
0024 #include <QTime>
0025 
0026 #include "common/resource.h"
0027 #include "common/storage.h"
0028 #include "common/resourceconfig.h"
0029 #include "common/log.h"
0030 #include "common/storage.h"
0031 #include "common/definitions.h"
0032 #include "common/store.h"
0033 #include "common/propertyparser.h"
0034 #include "common/resourceaccess.h"
0035 #include "common/commands.h"
0036 
0037 #include "sinksh_utils.h"
0038 #include "state.h"
0039 #include "syntaxtree.h"
0040 
0041 namespace SinkSelfTest
0042 {
0043 
0044 bool selfTest(const QStringList &args_, State &state)
0045 {
0046     using namespace Sink::ApplicationDomain;
0047     auto options = SyntaxTree::parseOptions(args_);
0048     if (options.positionalArguments.contains("stresstest")) {
0049         auto resource = SinkshUtils::parseUid(options.options.value("resource").first().toUtf8());
0050         qWarning() << "Stresstest on resource: " << resource;
0051         auto models = QSharedPointer<QList<QSharedPointer<QAbstractItemModel>>>::create();
0052 
0053         //Simulate the maillist, where we scroll down and trigger lots of fetchMore calls
0054         {
0055             Sink::Query query;
0056             query.resourceFilter(resource);
0057             query.limit(100);
0058             query.request<Mail::Subject>();
0059             query.request<Mail::Sender>();
0060             query.request<Mail::To>();
0061             query.request<Mail::Cc>();
0062             query.request<Mail::Bcc>();
0063             query.request<Mail::Date>();
0064             query.request<Mail::Unread>();
0065             query.request<Mail::Important>();
0066             query.request<Mail::Draft>();
0067             query.request<Mail::Sent>();
0068             query.request<Mail::Trash>();
0069             query.request<Mail::Folder>();
0070             query.sort<Mail::Date>();
0071             query.reduce<Mail::ThreadId>(Sink::Query::Reduce::Selector::max<Mail::Date>())
0072                 .count("count")
0073                 .collect<Mail::Unread>("unreadCollected")
0074                 .collect<Mail::Important>("importantCollected");
0075 
0076             auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query);
0077             models->append(model);
0078             QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [models, model, &state](const QModelIndex &start, const QModelIndex &end, const QVector<int> &roles) {
0079                 if (roles.contains(Sink::Store::ChildrenFetchedRole)) {
0080                     if (!model->canFetchMore({})) {
0081                         qWarning() << "Model complete: " << models->count();
0082                         models->removeAll(model);
0083                     } else {
0084                         qWarning() << "Fetching more";
0085                         //Simulate superfluous fetchMore calls
0086                         for (int i = 0; i < 10; i++) {
0087                             model->fetchMore({});
0088                         }
0089                         return;
0090                     }
0091                     if (models->isEmpty()) {
0092                         state.commandFinished();
0093                     }
0094                 }
0095             });
0096 
0097         }
0098 
0099         //Simluate lot's of mailviewers doing a bunch of queries
0100         {
0101             Sink::Query query;
0102             query.resourceFilter(resource);
0103             query.limit(10);
0104             query.request<Mail::Subject>();
0105             query.request<Mail::Sender>();
0106             query.request<Mail::To>();
0107             query.request<Mail::Cc>();
0108             query.request<Mail::Bcc>();
0109             query.request<Mail::Date>();
0110             query.request<Mail::Unread>();
0111             query.request<Mail::Important>();
0112             query.request<Mail::Draft>();
0113             query.request<Mail::Sent>();
0114             query.request<Mail::Trash>();
0115             query.request<Mail::Folder>();
0116             query.sort<Sink::ApplicationDomain::Mail::Date>();
0117             query.bloom<Sink::ApplicationDomain::Mail::ThreadId>();
0118 
0119             for (int i = 0; i < 50; i++) {
0120                 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query);
0121                 *models << model;
0122                 QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [models, model, &state](const QModelIndex &start, const QModelIndex &end, const QVector<int> &roles) {
0123                     if (roles.contains(Sink::Store::ChildrenFetchedRole)) {
0124                         models->removeAll(model);
0125                         qWarning() << "Model complete: " << models->count();
0126                         if (models->isEmpty()) {
0127                             state.commandFinished();
0128                         }
0129                     }
0130                         });
0131             }
0132         }
0133 
0134         return true;
0135     }
0136 
0137     state.printLine("Looking for resource plugins:");
0138     if (!Sink::ResourceFactory::load("sink.imap")) {
0139         state.printLine("Failure: Failed to load the imap resource", 1);
0140     } else {
0141         state.printLine("Success: Managed to load the imap resource", 1);
0142         state.printLine("Trying to start and connect to a resource.", 1);
0143         auto resourceAccess = Sink::ResourceAccessFactory::instance().getAccess("imap.selftest.resource", "sink.imap");
0144         resourceAccess->open();
0145         resourceAccess->sendCommand(Sink::Commands::PingCommand).addToContext(resourceAccess).then([&](const KAsync::Error &error) {
0146             if (error) {
0147                 state.printLine("Failure: Failed to start/connect to the resource.", 1);
0148             } else {
0149                 state.printLine("Success: Managed to start and connect to the resource.", 1);
0150             }
0151         }).exec().waitForFinished();
0152     }
0153 
0154     return false;
0155 }
0156 
0157 Syntax::List syntax()
0158 {
0159     Syntax syntax("selftest", QObject::tr("A selftest module."), &SinkSelfTest::selfTest, Syntax::EventDriven);
0160     return Syntax::List() << syntax;
0161 }
0162 
0163 REGISTER_SYNTAX(SinkSelfTest)
0164 
0165 }