File indexing completed on 2024-05-12 05:26:07

0001 /*
0002  * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) version 3, or any
0008  * later version accepted by the membership of KDE e.V. (or its
0009  * successor approved by the membership of KDE e.V.), which shall
0010  * act as a proxy defined in Section 6 of version 3 of the license.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0019  */
0020 
0021 #include "test.h"
0022 
0023 #include <QStandardPaths>
0024 #include <QDir>
0025 #include <QDebug>
0026 #include "facade.h"
0027 #include "facadefactory.h"
0028 #include "query.h"
0029 #include "resourceconfig.h"
0030 #include "definitions.h"
0031 
0032 using namespace Sink;
0033 
0034 void Sink::Test::initTest()
0035 {
0036     auto logIniFile = Sink::configLocation() + "/log.ini";
0037     auto areaAutocompletionFile = Sink::dataLocation() + "/debugAreas.ini";
0038 
0039     setTestModeEnabled(true);
0040     // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
0041     QDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).removeRecursively();
0042     // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::DataLocation);
0043     QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)).removeRecursively();
0044     // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
0045     QDir(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)).removeRecursively();
0046     // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
0047     QDir(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)).removeRecursively();
0048     // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
0049     QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)).removeRecursively();
0050     // qDebug() << "Removing " << QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
0051     QDir(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)).removeRecursively();
0052     Log::setPrimaryComponent("test");
0053 
0054     //We copy those files so we can control debug output from outside the test with sinksh
0055     {
0056         QDir dir;
0057         dir.mkpath(Sink::configLocation());
0058 
0059         QFile file(logIniFile);
0060         if (!file.open(QIODevice::ReadOnly)) {
0061             qWarning() << "Failed to open the file: " << logIniFile;
0062         } else {
0063             if (!file.copy(Sink::configLocation() + "/log.ini")) {
0064                 qWarning() << "Failed to move the file: " << Sink::configLocation() + "/log.ini";
0065             }
0066         }
0067     }
0068     {
0069         QFile file(areaAutocompletionFile);
0070         if (!file.open(QIODevice::ReadOnly)) {
0071             qWarning() << "Failed to open the file: " << logIniFile;
0072         }
0073         QDir dir;
0074         dir.mkpath(Sink::dataLocation());
0075         if (!file.copy(Sink::dataLocation() + "/debugAreas.ini")) {
0076             qWarning() << "Failed to move the file: " << Sink::configLocation() + "/log.ini";
0077         }
0078     }
0079 }
0080 
0081 void Sink::Test::setTestModeEnabled(bool enabled)
0082 {
0083     QStandardPaths::setTestModeEnabled(enabled);
0084     Sink::clearLocationCache();
0085     if (enabled) {
0086         qputenv("SINK_TESTMODE", "TRUE");
0087     } else {
0088         qunsetenv("SINK_TESTMODE");
0089     }
0090 }
0091 
0092 bool Sink::Test::testModeEnabled()
0093 {
0094     return !qEnvironmentVariableIsEmpty("SINK_TESTMODE");
0095 }
0096 
0097 template <typename T>
0098 class TestFacade : public Sink::StoreFacade<T>
0099 {
0100 public:
0101     static std::shared_ptr<TestFacade<T>> registerFacade(Test::TestAccount *testAccount, const QByteArray &instanceIdentifier = QByteArray())
0102     {
0103         static QMap<QByteArray, std::shared_ptr<TestFacade<T>>> map;
0104         auto facade = std::make_shared<TestFacade<T>>();
0105         facade->mTestAccount = testAccount;
0106         map.insert(instanceIdentifier, facade);
0107         bool alwaysReturnFacade = instanceIdentifier.isEmpty();
0108         Sink::FacadeFactory::instance().registerFacade<T, TestFacade<T>>("testresource", [alwaysReturnFacade](const Sink::ResourceContext &context) {
0109             if (alwaysReturnFacade) {
0110                 return map.value(QByteArray());
0111             }
0112             return map.value(context.resourceInstanceIdentifier);
0113         });
0114         return facade;
0115     }
0116     ~TestFacade() Q_DECL_OVERRIDE {};
0117     KAsync::Job<void> create(const T &domainObject) Q_DECL_OVERRIDE
0118     {
0119         mTestAccount->addEntity<T>(T::Ptr::create(domainObject));
0120         return KAsync::null<void>();
0121     };
0122     KAsync::Job<void> modify(const T &domainObject) Q_DECL_OVERRIDE
0123     {
0124         // mTestAccount->modifyEntity<T>(domainObject);
0125         return KAsync::null<void>();
0126     };
0127     KAsync::Job<void> move(const T &domainObject, const QByteArray &newResource) Q_DECL_OVERRIDE
0128     {
0129         // mTestAccount->moveEntity<T>(domainObject, newResource);
0130         return KAsync::null<void>();
0131     };
0132     KAsync::Job<void> copy(const T &domainObject, const QByteArray &newResource) Q_DECL_OVERRIDE
0133     {
0134         // mTestAccount->copyEntity<T>(domainObject, newResource);
0135         return KAsync::null<void>();
0136     };
0137     KAsync::Job<void> remove(const T &domainObject) Q_DECL_OVERRIDE
0138     {
0139         //FIXME
0140         // mTestAccount->removeEntity<T>(domainObject);
0141         return KAsync::null<void>();
0142     };
0143     QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename T::Ptr>::Ptr> load(const Sink::Query &query, const Sink::Log::Context &) Q_DECL_OVERRIDE
0144     {
0145         auto resultProvider = new Sink::ResultProvider<typename T::Ptr>();
0146         resultProvider->onDone([resultProvider]() {
0147             SinkTrace() << "Result provider is done";
0148             delete resultProvider;
0149         });
0150         // We have to do it this way, otherwise we're not setting the fetcher right
0151         auto emitter = resultProvider->emitter();
0152 
0153         resultProvider->setFetcher([query, resultProvider, this]() {
0154             SinkTrace() << "Running the fetcher.";
0155             SinkTrace() << "-------------------------.";
0156             for (const auto &res : mTestAccount->entities<T>()) {
0157                 resultProvider->add(res.template staticCast<T>());
0158             }
0159             resultProvider->initialResultSetComplete(true);
0160         });
0161         return qMakePair(KAsync::null(), emitter);
0162     }
0163 
0164     Test::TestAccount *mTestAccount;
0165 };
0166 
0167 Test::TestAccount Sink::Test::TestAccount::registerAccount()
0168 {
0169     Test::TestAccount account;
0170     account.mFacades.insert(ApplicationDomain::getTypeName<ApplicationDomain::Folder>(), TestFacade<ApplicationDomain::Folder>::registerFacade(&account));
0171     account.mFacades.insert(ApplicationDomain::getTypeName<ApplicationDomain::Mail>(), TestFacade<ApplicationDomain::Mail>::registerFacade(&account));
0172     account.identifier = "testresource.instance1";
0173     ResourceConfig::addResource(account.identifier, "testresource");
0174     QMap<QByteArray, QVariant> configuration;
0175     configuration.insert(ApplicationDomain::SinkResource::Account::name, account.identifier);
0176     configuration.insert(ApplicationDomain::SinkResource::Capabilities::name, QVariant::fromValue(QByteArrayList() << ApplicationDomain::ResourceCapabilities::Mail::drafts << ApplicationDomain::ResourceCapabilities::Mail::storage << ApplicationDomain::ResourceCapabilities::Mail::transport));
0177     ResourceConfig::configureResource(account.identifier, configuration);
0178     return account;
0179 }
0180 
0181 template<typename DomainType>
0182 void Sink::Test::TestAccount::addEntity(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)
0183 {
0184     mEntities[ApplicationDomain::getTypeName<DomainType>()].append(domainObject);
0185 }
0186 
0187 template<typename DomainType>
0188 typename DomainType::Ptr Sink::Test::TestAccount::createEntity()
0189 {
0190     auto entity = DomainType::Ptr::create(ApplicationDomain::ApplicationDomainType::createEntity<DomainType>(identifier));
0191     addEntity<DomainType>(entity);
0192     return entity;
0193 }
0194 
0195 template<typename DomainType>
0196 QList<Sink::ApplicationDomain::ApplicationDomainType::Ptr> Sink::Test::TestAccount::entities() const
0197 {
0198     return mEntities.value(ApplicationDomain::getTypeName<DomainType>());
0199 }
0200 
0201 
0202 #define REGISTER_TYPE(T)                                                          \
0203     template QList<Sink::ApplicationDomain::ApplicationDomainType::Ptr> Sink::Test::TestAccount::entities<T>() const;           \
0204     template void Sink::Test::TestAccount::addEntity<T>(const ApplicationDomain::ApplicationDomainType::Ptr &);           \
0205     template typename T::Ptr Sink::Test::TestAccount::createEntity<T>();
0206 
0207 SINK_REGISTER_TYPES()