GCC Code Coverage Report


Directory: ./
File: autotests/testinprocess.cpp
Date: 2023-04-20 22:59:23
Exec Total Coverage
Lines: 153 194 78.9%
Branches: 63 170 37.1%

Line Branch Exec Source
1 /*************************************************************************************
2 * Copyright 2015 by Sebastian K├╝gler <sebas@kde.org> *
3 * *
4 * This library is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
8 * *
9 * This library is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with this library; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
17 *************************************************************************************/
18 #include <QCoreApplication>
19 #include <QDBusConnectionInterface>
20 #include <QObject>
21 #include <QSignalSpy>
22 #include <QtTest>
23
24 #include "backendmanager_p.h"
25 #include "config.h"
26 #include "configmonitor.h"
27 #include "getconfigoperation.h"
28 #include "mode.h"
29 #include "output.h"
30 #include "setconfigoperation.h"
31
32 Q_LOGGING_CATEGORY(DISMAN, "disman")
33
34 using namespace Disman;
35
36 class TestInProcess : public QObject
37 {
38 Q_OBJECT
39
40 public:
41 explicit TestInProcess(QObject* parent = nullptr);
42
43 private Q_SLOTS:
44 void initTestCase();
45
46 void init();
47 void cleanup();
48
49 void loadConfig();
50
51 void testCreateJob();
52 void testModeSwitching();
53 void testBackendCaching();
54
55 void testConfigApply();
56 void testConfigMonitor();
57
58 private:
59 ConfigPtr m_config;
60 bool m_backendServiceInstalled = false;
61 };
62
63 1 TestInProcess::TestInProcess(QObject* parent)
64 : QObject(parent)
65 1 , m_config(nullptr)
66 {
67 1 }
68
69 1 void TestInProcess::initTestCase()
70 {
71 1 m_backendServiceInstalled = true;
72
73 1 const QString dismanServiceName = QStringLiteral("Disman");
74 1 QDBusConnectionInterface* bus = QDBusConnection::sessionBus().interface();
75
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 if (!bus->isServiceRegistered(dismanServiceName)) {
76 1 auto reply = bus->startService(dismanServiceName);
77
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!reply.isValid()) {
78 1 qDebug() << "D-Bus service Disman could not be started, skipping out-of-process tests";
79 1 m_backendServiceInstalled = false;
80 }
81 1 }
82 1 }
83
84 6 void TestInProcess::init()
85 {
86 6 qputenv("DISMAN_LOGGING", "false");
87 // Make sure we do everything in-process
88 6 qputenv("DISMAN_IN_PROCESS", "1");
89 // Use Fake backend with one of the json configs
90 6 qputenv("DISMAN_BACKEND", "fake");
91 6 qputenv("DISMAN_BACKEND_ARGS", "TEST_DATA=" TEST_DATA "multipleoutput.json");
92
93 6 Disman::BackendManager::instance()->shutdown_backend();
94 6 }
95
96 6 void TestInProcess::cleanup()
97 {
98 6 Disman::BackendManager::instance()->shutdown_backend();
99 6 }
100
101 1 void TestInProcess::loadConfig()
102 {
103 1 qputenv("DISMAN_IN_PROCESS", "1");
104 1 BackendManager::instance()->set_method(BackendManager::InProcess);
105
106 1 auto* op = new GetConfigOperation();
107
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(op->exec());
108 1 m_config = op->config();
109
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(m_config);
110
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(m_config->valid());
111 }
112
113 1 void TestInProcess::testModeSwitching()
114 {
115 1 Disman::BackendManager::instance()->shutdown_backend();
116 1 BackendManager::instance()->set_method(BackendManager::InProcess);
117 // Load QScreen backend in-process
118 1 qDebug() << "TT qscreen in-process";
119 1 qputenv("DISMAN_BACKEND", "qscreen");
120 1 auto op = new GetConfigOperation();
121
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(op->exec());
122 1 auto oc = op->config();
123
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(oc != nullptr);
124
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(oc->valid());
125
126 1 qDebug() << "TT fake in-process";
127 // Load the Fake backend in-process
128 1 qputenv("DISMAN_BACKEND", "fake");
129 1 auto ip = new GetConfigOperation();
130
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(ip->exec());
131 1 auto ic = ip->config();
132
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(ic != nullptr);
133
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(ic->valid());
134
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1 QVERIFY(ic->outputs().size());
135
136 1 Disman::ConfigPtr xc(nullptr);
137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (m_backendServiceInstalled) {
138 qDebug() << "TT xrandr out-of-process";
139 // Load the xrandr backend out-of-process
140 qputenv("DISMAN_BACKEND", "qscreen");
141 qputenv("DISMAN_IN_PROCESS", "0");
142 BackendManager::instance()->set_method(BackendManager::OutOfProcess);
143 auto xp = new GetConfigOperation();
144 QCOMPARE(BackendManager::instance()->method(), BackendManager::OutOfProcess);
145 QVERIFY(xp->exec());
146 xc = xp->config();
147 QVERIFY(xc != nullptr);
148 QVERIFY(xc->valid());
149 QVERIFY(xc->outputs().size());
150 }
151
152 1 qDebug() << "TT fake in-process";
153
154 1 qputenv("DISMAN_IN_PROCESS", "1");
155 1 BackendManager::instance()->set_method(BackendManager::InProcess);
156 // Load the Fake backend in-process
157 1 qputenv("DISMAN_BACKEND", "fake");
158 1 auto fp = new GetConfigOperation();
159
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QCOMPARE(BackendManager::instance()->method(), BackendManager::InProcess);
160
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(fp->exec());
161 1 auto fc = fp->config();
162
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(fc != nullptr);
163
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(fc->valid());
164
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1 QVERIFY(fc->outputs().size());
165
166
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(oc->valid());
167
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(ic->valid());
168
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (xc) {
169 QVERIFY(xc->valid());
170 }
171
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(fc->valid());
172
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
1 }
173
174 1 void TestInProcess::testBackendCaching()
175 {
176 1 Disman::BackendManager::instance()->shutdown_backend();
177 1 qputenv("DISMAN_BACKEND", "fake");
178 1 QElapsedTimer t;
179 1 BackendManager::instance()->set_method(BackendManager::InProcess);
180
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QCOMPARE(BackendManager::instance()->method(), BackendManager::InProcess);
181 int t_cold;
182 int t_warm;
183
184 {
185 1 t.start();
186 1 auto cp = new GetConfigOperation();
187 1 cp->exec();
188 1 auto cc = cp->config();
189 1 t_cold = t.nsecsElapsed();
190
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(cc != nullptr);
191
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(cc->valid());
192
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1 QVERIFY(cc->outputs().size());
193
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 }
194 {
195 // Disman::BackendManager::instance()->shutdown_backend();
196
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QCOMPARE(BackendManager::instance()->method(), BackendManager::InProcess);
197 1 t.start();
198 1 auto cp = new GetConfigOperation();
199 1 cp->exec();
200 1 auto cc = cp->config();
201 1 t_warm = t.nsecsElapsed();
202
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(cc != nullptr);
203
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(cc->valid());
204
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1 QVERIFY(cc->outputs().size());
205
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 }
206 {
207 1 auto cp = new GetConfigOperation();
208
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QCOMPARE(BackendManager::instance()->method(), BackendManager::InProcess);
209 1 cp->exec();
210 1 auto cc = cp->config();
211
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(cc != nullptr);
212
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(cc->valid());
213
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1 QVERIFY(cc->outputs().size());
214
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 }
215 // Check if all our configs are still valid after the backend is gone
216 1 Disman::BackendManager::instance()->shutdown_backend();
217
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (m_backendServiceInstalled) {
219 // qputenv("DISMAN_BACKEND", "qscreen");
220 qputenv("DISMAN_IN_PROCESS", "0");
221 BackendManager::instance()->set_method(BackendManager::OutOfProcess);
222 QCOMPARE(BackendManager::instance()->method(), BackendManager::OutOfProcess);
223 int t_x_cold;
224
225 {
226 t.start();
227 auto xp = new GetConfigOperation();
228 xp->exec();
229 t_x_cold = t.nsecsElapsed();
230 auto xc = xp->config();
231 QVERIFY(xc != nullptr);
232 }
233 t.start();
234 auto xp = new GetConfigOperation();
235 xp->exec();
236 int t_x_warm = t.nsecsElapsed();
237 auto xc = xp->config();
238 QVERIFY(xc != nullptr);
239
240 // Make sure in-process is faster
241 QVERIFY(t_cold > t_warm);
242 QVERIFY(t_x_cold > t_x_warm);
243 QVERIFY(t_x_cold > t_cold);
244 return;
245 qDebug() << "ip speedup for cached access:" << (qreal)((qreal)t_cold / (qreal)t_warm);
246 qDebug() << "oop speedup for cached access:" << (qreal)((qreal)t_x_cold / (qreal)t_x_warm);
247 qDebug() << "out-of vs. in-process speedup:" << (qreal)((qreal)t_x_warm / (qreal)t_warm);
248 qDebug() << "cold oop: " << ((qreal)t_x_cold / 1000000);
249 qDebug() << "cached oop: " << ((qreal)t_x_warm / 1000000);
250 qDebug() << "cold in process: " << ((qreal)t_cold / 1000000);
251 qDebug() << "cached in process: " << ((qreal)t_warm / 1000000);
252 }
253 }
254
255 1 void TestInProcess::testCreateJob()
256 {
257 1 Disman::BackendManager::instance()->shutdown_backend();
258 {
259 1 BackendManager::instance()->set_method(BackendManager::InProcess);
260 1 auto op = new GetConfigOperation();
261 1 auto _op = qobject_cast<GetConfigOperation*>(op);
262
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 QVERIFY(_op != nullptr);
263
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QCOMPARE(BackendManager::instance()->method(), BackendManager::InProcess);
264
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(op->exec());
265 1 auto cc = op->config();
266
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(cc != nullptr);
267
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 QVERIFY(cc->valid());
268
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 }
269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (m_backendServiceInstalled) {
270 BackendManager::instance()->set_method(BackendManager::OutOfProcess);
271 auto op = new GetConfigOperation();
272 auto _op = qobject_cast<GetConfigOperation*>(op);
273 QVERIFY(_op != nullptr);
274 QCOMPARE(BackendManager::instance()->method(), BackendManager::OutOfProcess);
275 QVERIFY(op->exec());
276 auto cc = op->config();
277 QVERIFY(cc != nullptr);
278 QVERIFY(cc->valid());
279 }
280 1 Disman::BackendManager::instance()->shutdown_backend();
281 1 BackendManager::instance()->set_method(BackendManager::InProcess);
282 }
283
284 1 void TestInProcess::testConfigApply()
285 {
286 1 qputenv("DISMAN_BACKEND", "fake");
287 1 Disman::BackendManager::instance()->shutdown_backend();
288 1 BackendManager::instance()->set_method(BackendManager::InProcess);
289 1 auto op = new GetConfigOperation();
290 1 op->exec();
291 1 auto config = op->config();
292 // qDebug() << "op:" << config->outputs().size();
293 1 auto output = config->outputs().begin()->second;
294 // qDebug() << "res:" << output->geometry();
295 // qDebug() << "modes:" << output->modes();
296 1 auto m0 = output->modes().begin()->second;
297 // qDebug() << "m0:" << m0->id() << m0;
298 1 output->set_mode(m0);
299
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(Config::can_be_applied(config));
300
301 // expected to fail, SetConfigOperation is out-of-process only
302 1 auto setop = new SetConfigOperation(config);
303
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(!setop->has_error());
304
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(setop->exec());
305
306
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(!setop->has_error());
307
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 }
308
309 1 void TestInProcess::testConfigMonitor()
310 {
311 1 qputenv("DISMAN_BACKEND", "fake");
312
313 1 Disman::BackendManager::instance()->shutdown_backend();
314 1 BackendManager::instance()->set_method(BackendManager::InProcess);
315 1 auto op = new GetConfigOperation();
316 1 op->exec();
317 1 auto config = op->config();
318 // qDebug() << "op:" << config->outputs().size();
319 1 auto output = config->outputs().begin()->second;
320 // qDebug() << "res:" << output->geometry();
321 // qDebug() << "modes:" << output->modes();
322 1 auto m0 = output->modes().begin()->second;
323 // qDebug() << "m0:" << m0->id() << m0;
324 1 output->set_mode(m0);
325
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(Config::can_be_applied(config));
326
327 1 QSignalSpy monitorSpy(ConfigMonitor::instance(), &ConfigMonitor::configuration_changed);
328 1 qDebug() << "MOnitorspy connencted.";
329 1 ConfigMonitor::instance()->add_config(config);
330
331 1 auto setop = new SetConfigOperation(config);
332
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(!setop->has_error());
333 // do not cal setop->exec(), this must not block as the signalspy already blocks
334
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 QVERIFY(monitorSpy.wait(500));
335
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
1 }
336
337 1 QTEST_GUILESS_MAIN(TestInProcess)
338
339 #include "testinprocess.moc"
340