Akonadi

qtest_akonadi.h
1/* This file is based on qtest_kde.h from kdelibs
2 SPDX-FileCopyrightText: 2006 David Faure <faure@kde.org>
3 SPDX-FileCopyrightText: 2009 Volker Krause <vkrause@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only
6*/
7
8#pragma once
9
10#include "agentinstance.h"
11#include "agentmanager.h"
12#include "collectionfetchscope.h"
13#include "collectionpathresolver.h"
14#include "itemfetchscope.h"
15#include "monitor.h"
16#include "servermanager.h"
17
18#include <QDBusConnection>
19#include <QDBusInterface>
20#include <QDBusReply>
21#include <QSignalSpy>
22#include <QTest>
23#include <QTimer>
24
25/**
26 * \short Akonadi Replacement for QTEST_MAIN from QTestLib
27 *
28 * This macro should be used for classes that run inside the Akonadi Testrunner.
29 * So instead of writing QTEST_MAIN( TestClass ) you write
30 * QTEST_AKONADIMAIN( TestClass ).
31 *
32 * Unlike QTEST_MAIN, this macro actually does call QApplication::exec() so
33 * that the application is running during test execution. This is needed
34 * for proper clean up of Sessions.
35 *
36 * \param TestObject The class you use for testing.
37 *
38 * \see QTestLib
39 * \see QTEST_KDEMAIN
40 */
41#define QTEST_AKONADIMAIN(TestObject) \
42 int main(int argc, char *argv[]) \
43 { \
44 qputenv("LC_ALL", "C"); \
45 qunsetenv("KDE_COLOR_DEBUG"); \
46 QApplication app(argc, argv); \
47 app.setApplicationName(QStringLiteral("qttest")); \
48 app.setOrganizationDomain(QStringLiteral("kde.org")); \
49 app.setOrganizationName(QStringLiteral("KDE")); \
50 QGuiApplication::setQuitOnLastWindowClosed(false); \
51 QCoreApplication::setQuitLockEnabled(false); \
52 qRegisterMetaType<QList<QUrl>>(); \
53 int result = 0; \
54 QTimer::singleShot(0, &app, [argc, argv, &result]() { \
55 TestObject tc; \
56 result = QTest::qExec(&tc, argc, argv); \
57 qApp->quit(); \
58 }); \
59 app.exec(); \
60 return result; \
61 }
62
63namespace AkonadiTest
64{
65/**
66 * Checks that the test is running in the proper test environment
67 */
68void checkTestIsIsolated()
69{
70 if (qEnvironmentVariableIsEmpty("TESTRUNNER_DB_ENVIRONMENT"))
71 qFatal("This test must be run using ctest, in order to use the testrunner environment. Aborting, to avoid messing up your real akonadi");
72 if (!qgetenv("XDG_DATA_HOME").contains("testrunner"))
73 qFatal("Did you forget to run the test using QTEST_AKONADIMAIN?");
74}
75
76/**
77 * Switch all resources offline to reduce interference from them
78 */
79void setAllResourcesOffline()
80{
81 // switch all resources offline to reduce interference from them
82 const auto lst = Akonadi::AgentManager::self()->instances();
83 for (Akonadi::AgentInstance agent : lst) {
84 agent.setIsOnline(false);
85 }
86}
87
88template<typename Object, typename Func>
89bool akWaitForSignal(Object sender, Func member, int timeout = 1000)
90{
91 QSignalSpy spy(sender, member);
92 bool ok = false;
93 [&]() {
94 QTRY_VERIFY_WITH_TIMEOUT(spy.count() > 0, timeout);
95 ok = true;
96 }();
97 return ok;
98}
99
100bool akWaitForSignal(const QObject *sender, const char *member, int timeout = 1000)
101{
102 QSignalSpy spy(sender, member);
103 bool ok = false;
104 [&]() {
105 QTRY_VERIFY_WITH_TIMEOUT(spy.count() > 0, timeout);
106 ok = true;
107 }();
108 return ok;
109}
110
111qint64 collectionIdFromPath(const QString &path)
112{
113 auto resolver = new Akonadi::CollectionPathResolver(path);
114 bool success = resolver->exec();
115 if (!success) {
116 qDebug() << "path resolution for " << path << " failed: " << resolver->errorText();
117 return -1;
118 }
119 qint64 id = resolver->collection();
120 return id;
121}
122
123QString testrunnerServiceName()
124{
125 const QString pid = QString::fromLocal8Bit(qgetenv("AKONADI_TESTRUNNER_PID"));
126 Q_ASSERT(!pid.isEmpty());
127 return QStringLiteral("org.kde.Akonadi.Testrunner-") + pid;
128}
129
130bool restartAkonadiServer()
131{
132 QDBusInterface testrunnerIface(testrunnerServiceName(), QStringLiteral("/"), QStringLiteral("org.kde.Akonadi.Testrunner"), QDBusConnection::sessionBus());
133 if (!testrunnerIface.isValid()) {
134 qWarning() << "Unable to get a dbus interface to the testrunner!";
135 }
136
137 QDBusReply<void> reply = testrunnerIface.call(QStringLiteral("restartAkonadiServer"));
138 if (!reply.isValid()) {
139 qWarning() << reply.error();
140 return false;
142 return true;
143 } else {
144 bool ok = false;
145 [&]() {
147 QTRY_VERIFY_WITH_TIMEOUT(spy.count() > 0, 10000);
148 ok = true;
149 }();
150 return ok;
151 }
152}
153
154bool trackAkonadiProcess(bool track)
155{
156 QDBusInterface testrunnerIface(testrunnerServiceName(), QStringLiteral("/"), QStringLiteral("org.kde.Akonadi.Testrunner"), QDBusConnection::sessionBus());
157 if (!testrunnerIface.isValid()) {
158 qWarning() << "Unable to get a dbus interface to the testrunner!";
159 }
160
161 QDBusReply<void> reply = testrunnerIface.call(QStringLiteral("trackAkonadiProcess"), track);
162 if (!reply.isValid()) {
163 qWarning() << reply.error();
164 return false;
165 } else {
166 return true;
167 }
168}
169
170std::unique_ptr<Akonadi::Monitor> getTestMonitor()
171{
172 auto m = new Akonadi::Monitor();
173 m->fetchCollection(true);
174 m->setCollectionMonitored(Akonadi::Collection::root(), true);
175 m->setAllMonitored(true);
176 auto &itemFS = m->itemFetchScope();
177 itemFS.setAncestorRetrieval(Akonadi::ItemFetchScope::All);
178 auto &colFS = m->collectionFetchScope();
179 colFS.setAncestorRetrieval(Akonadi::CollectionFetchScope::All);
180
181 QSignalSpy readySpy(m, &Akonadi::Monitor::monitorReady);
182 readySpy.wait();
183
184 return std::unique_ptr<Akonadi::Monitor>(m);
185}
186
187} // namespace
188
189/**
190 * Runs an Akonadi::Job synchronously and aborts if the job failed.
191 * Similar to QVERIFY( job->exec() ) but includes the job error message
192 * in the output in case of a failure.
193 */
194#define AKVERIFYEXEC(job) QVERIFY2(job->exec(), job->errorString().toUtf8().constData())
A representation of an agent instance.
static AgentManager * self()
Returns the global instance of the agent manager.
AgentInstance::List instances() const
Returns the list of all available agent instances.
@ All
Retrieve all ancestors, up to Collection::root()
static Collection root()
Returns the root collection.
@ All
Retrieve all ancestors, up to Collection::root()
Monitors an item or collection for changes.
Definition monitor.h:72
static bool isRunning()
Checks if the server is available currently.
void started()
Emitted whenever the server becomes fully operational.
static ServerManager * self()
Returns the singleton instance of this class, for connecting to its signals.
QString path(const QString &relativePath)
QDBusConnection sessionBus()
const QDBusError & error()
bool isValid() const const
QString fromLocal8Bit(QByteArrayView str)
bool isEmpty() const const
QTRY_VERIFY_WITH_TIMEOUT(condition, timeout)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:38 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.