Akonadi

qtest_akonadi.h
1 /* This file is based on qtest_kde.h from kdelibs
2  SPDX-FileCopyrightText: 2006 David Faure <[email protected]>
3  SPDX-FileCopyrightText: 2009 Volker Krause <[email protected]>
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  qRegisterMetaType<QList<QUrl>>(); \
52  int result = 0; \
53  QTimer::singleShot(0, &app, [argc, argv, &result]() { \
54  TestObject tc; \
55  result = QTest::qExec(&tc, argc, argv); \
56  qApp->quit(); \
57  }); \
58  app.exec(); \
59  return result; \
60  }
61 
62 namespace AkonadiTest
63 {
64 /**
65  * Checks that the test is running in the proper test environment
66  */
67 void checkTestIsIsolated()
68 {
69  if (qEnvironmentVariableIsEmpty("TESTRUNNER_DB_ENVIRONMENT"))
70  qFatal("This test must be run using ctest, in order to use the testrunner environment. Aborting, to avoid messing up your real akonadi");
71  if (!qgetenv("XDG_DATA_HOME").contains("testrunner"))
72  qFatal("Did you forget to run the test using QTEST_AKONADIMAIN?");
73 }
74 
75 /**
76  * Switch all resources offline to reduce interference from them
77  */
78 void setAllResourcesOffline()
79 {
80  // switch all resources offline to reduce interference from them
81  const auto lst = Akonadi::AgentManager::self()->instances();
82  for (Akonadi::AgentInstance agent : lst) {
83  agent.setIsOnline(false);
84  }
85 }
86 
87 template<typename Object, typename Func> bool akWaitForSignal(Object sender, Func member, int timeout = 1000)
88 {
89  QSignalSpy spy(sender, member);
90  bool ok = false;
91  [&]() {
92  QTRY_VERIFY_WITH_TIMEOUT(spy.count() > 0, timeout);
93  ok = true;
94  }();
95  return ok;
96 }
97 
98 bool akWaitForSignal(const QObject *sender, const char *member, int timeout = 1000)
99 {
100  QSignalSpy spy(sender, member);
101  bool ok = false;
102  [&]() {
103  QTRY_VERIFY_WITH_TIMEOUT(spy.count() > 0, timeout);
104  ok = true;
105  }();
106  return ok;
107 }
108 
109 qint64 collectionIdFromPath(const QString &path)
110 {
111  auto resolver = new Akonadi::CollectionPathResolver(path);
112  bool success = resolver->exec();
113  if (!success) {
114  qDebug() << "path resolution for " << path << " failed: " << resolver->errorText();
115  return -1;
116  }
117  qint64 id = resolver->collection();
118  return id;
119 }
120 
121 QString testrunnerServiceName()
122 {
123  const QString pid = QString::fromLocal8Bit(qgetenv("AKONADI_TESTRUNNER_PID"));
124  Q_ASSERT(!pid.isEmpty());
125  return QStringLiteral("org.kde.Akonadi.Testrunner-") + pid;
126 }
127 
128 bool restartAkonadiServer()
129 {
130  QDBusInterface testrunnerIface(testrunnerServiceName(), QStringLiteral("/"), QStringLiteral("org.kde.Akonadi.Testrunner"), QDBusConnection::sessionBus());
131  if (!testrunnerIface.isValid()) {
132  qWarning() << "Unable to get a dbus interface to the testrunner!";
133  }
134 
135  QDBusReply<void> reply = testrunnerIface.call(QStringLiteral("restartAkonadiServer"));
136  if (!reply.isValid()) {
137  qWarning() << reply.error();
138  return false;
139  } else if (Akonadi::ServerManager::isRunning()) {
140  return true;
141  } else {
142  bool ok = false;
143  [&]() {
145  QTRY_VERIFY_WITH_TIMEOUT(spy.count() > 0, 10000);
146  ok = true;
147  }();
148  return ok;
149  }
150 }
151 
152 bool trackAkonadiProcess(bool track)
153 {
154  QDBusInterface testrunnerIface(testrunnerServiceName(), QStringLiteral("/"), QStringLiteral("org.kde.Akonadi.Testrunner"), QDBusConnection::sessionBus());
155  if (!testrunnerIface.isValid()) {
156  qWarning() << "Unable to get a dbus interface to the testrunner!";
157  }
158 
159  QDBusReply<void> reply = testrunnerIface.call(QStringLiteral("trackAkonadiProcess"), track);
160  if (!reply.isValid()) {
161  qWarning() << reply.error();
162  return false;
163  } else {
164  return true;
165  }
166 }
167 
168 std::unique_ptr<Akonadi::Monitor> getTestMonitor()
169 {
170  auto m = new Akonadi::Monitor();
171  m->fetchCollection(true);
172  m->setCollectionMonitored(Akonadi::Collection::root(), true);
173  m->setAllMonitored(true);
174  auto &itemFS = m->itemFetchScope();
175  itemFS.setAncestorRetrieval(Akonadi::ItemFetchScope::All);
176  auto &colFS = m->collectionFetchScope();
177  colFS.setAncestorRetrieval(Akonadi::CollectionFetchScope::All);
178 
179  QSignalSpy readySpy(m, &Akonadi::Monitor::monitorReady);
180  readySpy.wait();
181 
182  return std::unique_ptr<Akonadi::Monitor>(m);
183 }
184 
185 } // namespace
186 
187 /**
188  * Runs an Akonadi::Job synchronously and aborts if the job failed.
189  * Similar to QVERIFY( job->exec() ) but includes the job error message
190  * in the output in case of a failure.
191  */
192 #define AKVERIFYEXEC(job) QVERIFY2(job->exec(), job->errorString().toUtf8().constData())
193 
@ All
Retrieve all ancestors, up to Collection::root()
bool isValid() const const
static ServerManager * self()
Returns the singleton instance of this class, for connecting to its signals.
Monitors an item or collection for changes.
Definition: monitor.h:71
const QDBusError & error()
QDBusConnection sessionBus()
QString fromLocal8Bit(const char *str, int size)
static bool isRunning()
Checks if the server is available currently.
bool isEmpty() const const
void started()
Emitted whenever the server becomes fully operational.
static Collection root()
Returns the root collection.
Definition: collection.cpp:287
@ All
Retrieve all ancestors, up to Collection::root()
QTRY_VERIFY_WITH_TIMEOUT(condition, timeout)
static AgentManager * self()
Returns the global instance of the agent manager.
AgentInstance::List instances() const
Returns the list of all available agent instances.
A representation of an agent instance.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jun 25 2022 06:00:32 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.