testkwaylandbackend.cpp 10.6 KB
Newer Older
1
/*************************************************************************************
Sebastian Kügler's avatar
Sebastian Kügler committed
2
 *  Copyright 2014-2015 Sebastian Kügler <sebas@kde.org>                             *
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 *                                                                                   *
 *  This library is free software; you can redistribute it and/or                    *
 *  modify it under the terms of the GNU Lesser General Public                       *
 *  License as published by the Free Software Foundation; either                     *
 *  version 2.1 of the License, or (at your option) any later version.               *
 *                                                                                   *
 *  This library is distributed in the hope that it will be useful,                  *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                *
 *  Lesser General Public License for more details.                                  *
 *                                                                                   *
 *  You should have received a copy of the GNU Lesser General Public                 *
 *  License along with this library; if not, write to the Free Software              *
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA       *
 *************************************************************************************/

19
#include <QCoreApplication>
Sebastian Kügler's avatar
Sebastian Kügler committed
20
#include <QCryptographicHash>
21
22
#include <QtTest>
#include <QObject>
23

24
25
#include "../src/backendmanager_p.h"
#include "../src/getconfigoperation.h"
26
#include "../src/setconfigoperation.h"
27
#include "../src/config.h"
28
#include "../src/configmonitor.h"
29
30
31
32
#include "../src/output.h"
#include "../src/mode.h"
#include "../src/edid.h"

33
34
35
36
// KWayland
#include <KWayland/Server/display.h>
#include <KWayland/Server/outputdevice_interface.h>

37
#include "waylandtestserver.h"
38

Allen Winter's avatar
Allen Winter committed
39
Q_LOGGING_CATEGORY(KSCREEN_WAYLAND, "kscreen.kwayland")
40
41
42
43
44
45
46

using namespace KScreen;

class testWaylandBackend : public QObject
{
    Q_OBJECT

47
48
49
public:
    explicit testWaylandBackend(QObject *parent = nullptr);

50
51
private Q_SLOTS:
    void initTestCase();
52
    void cleanupTestCase();
53
    void loadConfig();
54

55
    void verifyConfig();
56
    void verifyOutputs();
Sebastian Kügler's avatar
Sebastian Kügler committed
57
    void verifyModes();
58
    void verifyScreen();
Sebastian Kügler's avatar
Sebastian Kügler committed
59
    void verifyIds();
60
    void verifyFeatures();
61
    void simpleWrite();
62
63
    void addOutput();
    void removeOutput();
64
    void testEdid();
65

66

67
private:
68
    ConfigPtr m_config;
69
    WaylandTestServer *m_server;
70
    KWayland::Server::OutputDeviceInterface *m_serverOutputDevice;
71
72
};

73
74
testWaylandBackend::testWaylandBackend(QObject *parent)
    : QObject(parent)
75
    , m_config(nullptr)
76
{
77
    qputenv("KSCREEN_LOGGING", "false");
78
    m_server = new WaylandTestServer(this);
Frederik Gladhorn's avatar
Frederik Gladhorn committed
79
    m_server->setConfig(QLatin1String(TEST_DATA) + QLatin1String("multipleoutput.json"));
80
81
}

82
83
void testWaylandBackend::initTestCase()
{
84
    qputenv("KSCREEN_BACKEND", "kwayland");
85
    KScreen::BackendManager::instance()->shutdownBackend();
Sebastian Kügler's avatar
Sebastian Kügler committed
86
87
    // This is how KWayland will pick up the right socket,
    // and thus connect to our internal test server.
Frederik Gladhorn's avatar
Frederik Gladhorn committed
88
    setenv("WAYLAND_DISPLAY", s_socketName.toLocal8Bit().constData(), 1);
Sebastian Kügler's avatar
Sebastian Kügler committed
89
    m_server->start();
90
91
92
93

    GetConfigOperation *op = new GetConfigOperation();
    op->exec();
    m_config = op->config();
Sebastian Kügler's avatar
Sebastian Kügler committed
94
}
95

96
void testWaylandBackend::loadConfig()
97
{
98
99
100
    GetConfigOperation *op = new GetConfigOperation();
    op->exec();
    m_config = op->config();
Sebastian Kügler's avatar
Sebastian Kügler committed
101
    QVERIFY(m_config->isValid());
Sebastian Kügler's avatar
Sebastian Kügler committed
102
    qCDebug(KSCREEN_WAYLAND) << "ops" << m_config->outputs();
103
104
}

105
106
void testWaylandBackend::verifyConfig()
{
107
    QVERIFY(m_config != nullptr);
108
109
110
111
112
    if (!m_config) {
        QSKIP("Wayland backend invalid", SkipAll);
    }
}

113
114
void testWaylandBackend::verifyScreen()
{
115
    ScreenPtr screen = m_config->screen();
116

117
118
119
120
121
122
123
124
125
126
127
    QVERIFY(screen->minSize().width() <= screen->maxSize().width());
    QVERIFY(screen->minSize().height() <= screen->maxSize().height());

    QVERIFY(screen->minSize().width() <= screen->currentSize().width());
    QVERIFY(screen->minSize().height() <= screen->currentSize().height());

    QVERIFY(screen->maxSize().width() >= screen->currentSize().width());
    QVERIFY(screen->maxSize().height() >= screen->currentSize().height());
    QVERIFY(m_config->screen()->maxActiveOutputsCount() > 0);
}

128
129
void testWaylandBackend::verifyOutputs()
{
130
    bool primaryFound = false;
Sebastian Kügler's avatar
Sebastian Kügler committed
131
    Q_FOREACH (const KScreen::OutputPtr op, m_config->outputs()) {
132
133
134
135
        if (op->isPrimary()) {
            primaryFound = true;
        }
    }
Sebastian Kügler's avatar
Sebastian Kügler committed
136
    //qCDebug(KSCREEN_WAYLAND) << "Primary found? " << primaryFound << m_config->outputs();
Sebastian Kügler's avatar
Sebastian Kügler committed
137
    QVERIFY(primaryFound);
138
    QVERIFY(m_config->outputs().count());
139
    QCOMPARE(m_server->outputCount(), m_config->outputs().count());
140

141
    KScreen::OutputPtr primary = m_config->primaryOutput();
Sebastian Kügler's avatar
Sebastian Kügler committed
142
    QVERIFY(primary->isEnabled());
143
144
145
    QVERIFY(primary->isConnected());

    QList<int> ids;
Sebastian Kügler's avatar
Sebastian Kügler committed
146
    Q_FOREACH (const auto &output, m_config->outputs()) {
147
148
149
150
151
        QVERIFY(!output->name().isEmpty());
        QVERIFY(output->id() > -1);
        QVERIFY(output->isConnected());
        QVERIFY(output->geometry() != QRectF(1,1,1,1));
        QVERIFY(output->geometry() != QRectF());
Sebastian Kügler's avatar
Sebastian Kügler committed
152
        QVERIFY(output->sizeMm() != QSize());
Friedrich W. H. Kossebau's avatar
Friedrich W. H. Kossebau committed
153
        QVERIFY(output->edid() != nullptr);
154
        QVERIFY(output->preferredModes().size() == 1);
155
156
157
158
159
160
        QCOMPARE(output->rotation(), Output::None);
        QVERIFY(!ids.contains(output->id()));
        ids << output->id();
    }
}

Sebastian Kügler's avatar
Sebastian Kügler committed
161
162
void testWaylandBackend::verifyModes()
{
163
    KScreen::OutputPtr primary = m_config->primaryOutput();
Sebastian Kügler's avatar
Sebastian Kügler committed
164
165
166
    QVERIFY(primary);
    QVERIFY(primary->modes().count() > 0);

Sebastian Kügler's avatar
Sebastian Kügler committed
167
168
    Q_FOREACH (const auto &output, m_config->outputs()) {
        Q_FOREACH (auto mode, output->modes()) {
Sebastian Kügler's avatar
Sebastian Kügler committed
169
170
            QVERIFY(!mode->name().isEmpty());
            QVERIFY(mode->refreshRate() > 0);
Sebastian Kügler's avatar
Sebastian Kügler committed
171
            QVERIFY(mode->size().isValid());
Sebastian Kügler's avatar
Sebastian Kügler committed
172
173
174
175
        }
    }
}

Sebastian Kügler's avatar
Sebastian Kügler committed
176
177
void testWaylandBackend::verifyIds()
{
178
    QList<quint32> ids;
Sebastian Kügler's avatar
Sebastian Kügler committed
179
    Q_FOREACH (const auto &output, m_config->outputs()) {
180
        QVERIFY(ids.contains(output->id()) == false);
Sebastian Kügler's avatar
Sebastian Kügler committed
181
        QVERIFY(output->id() > 0);
182
        ids << output->id();
Sebastian Kügler's avatar
Sebastian Kügler committed
183
184
185
    }
}

186
187
188
189
190
191
192
193
194
195
196
197
void testWaylandBackend::simpleWrite()
{
    KScreen::BackendManager::instance()->shutdownBackend();
    GetConfigOperation *op = new GetConfigOperation();
    op->exec();
    m_config = op->config();
    auto output = m_config->output(1);
    auto n_mode = QStringLiteral("800x600@60");
    auto o_mode = output->currentModeId();
    output->setCurrentModeId(n_mode);

    auto setop = new SetConfigOperation(m_config);
Sebastian Kügler's avatar
Sebastian Kügler committed
198
    QVERIFY(setop->exec());
199
200
}

201
202
void testWaylandBackend::cleanupTestCase()
{
203
    m_config->deleteLater();
204
    KScreen::BackendManager::instance()->shutdownBackend();
205
206
}

207
208
209
210
211
212
void testWaylandBackend::addOutput()
{
    KScreen::BackendManager::instance()->shutdownBackend();
    GetConfigOperation *op = new GetConfigOperation();
    op->exec();
    auto config = op->config();
213
    QCOMPARE(config->outputs().count(), 2);
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
    KScreen::ConfigMonitor *monitor = KScreen::ConfigMonitor::instance();
    monitor->addConfig(config);
    QSignalSpy configSpy(monitor, &KScreen::ConfigMonitor::configurationChanged);

    // Now add an outputdevice on the server side
    m_serverOutputDevice = m_server->display()->createOutputDevice(this);
    m_serverOutputDevice->setUuid("1337");

    OutputDeviceInterface::Mode m0;
    m0.id = 0;
    m0.size = QSize(800, 600);
    m0.flags = OutputDeviceInterface::ModeFlags(OutputDeviceInterface::ModeFlag::Preferred);
    m_serverOutputDevice->addMode(m0);

    OutputDeviceInterface::Mode m1;
    m1.id = 1;
    m1.size = QSize(1024, 768);
    m_serverOutputDevice->addMode(m1);

    OutputDeviceInterface::Mode m2;
    m2.id = 2;
    m2.size = QSize(1280, 1024);
    m2.refreshRate = 90000;
    m_serverOutputDevice->addMode(m2);

    m_serverOutputDevice->setCurrentMode(1);

    m_serverOutputDevice->create();

Sebastian Kügler's avatar
Sebastian Kügler committed
243
244
245
    QVERIFY(configSpy.wait());
    //QTRY_VERIFY(configSpy.count());

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
    GetConfigOperation *op2 = new GetConfigOperation();
    op2->exec();
    auto newconfig = op2->config();
    QCOMPARE(newconfig->outputs().count(), 3);
}

void testWaylandBackend::removeOutput()
{
    KScreen::BackendManager::instance()->shutdownBackend();
    GetConfigOperation *op = new GetConfigOperation();
    op->exec();
    auto config = op->config();
    QCOMPARE(config->outputs().count(), 3);
    KScreen::ConfigMonitor *monitor = KScreen::ConfigMonitor::instance();
    monitor->addConfig(config);
    QSignalSpy configSpy(monitor, &KScreen::ConfigMonitor::configurationChanged);

    delete m_serverOutputDevice;
Sebastian Kügler's avatar
Sebastian Kügler committed
264
    QVERIFY(configSpy.wait());
265
266
267
268
269
    GetConfigOperation *op2 = new GetConfigOperation();
    op2->exec();
    auto newconfig = op2->config();
    QCOMPARE(newconfig->outputs().count(), 2);
}
270

271
272
273
274
275
void testWaylandBackend::testEdid()
{
    m_server->showOutputs();

    QByteArray data = QByteArray::fromBase64("AP///////wAQrBbwTExLQQ4WAQOANCB46h7Frk80sSYOUFSlSwCBgKlA0QBxTwEBAQEBAQEBKDyAoHCwI0AwIDYABkQhAAAaAAAA/wBGNTI1TTI0NUFLTEwKAAAA/ABERUxMIFUyNDEwCiAgAAAA/QA4TB5REQAKICAgICAgAToCAynxUJAFBAMCBxYBHxITFCAVEQYjCQcHZwMMABAAOC2DAQAA4wUDAQI6gBhxOC1AWCxFAAZEIQAAHgEdgBhxHBYgWCwlAAZEIQAAngEdAHJR0B4gbihVAAZEIQAAHowK0Iog4C0QED6WAAZEIQAAGAAAAAAAAAAAAAAAAAAAPg==");
Sebastian Kügler's avatar
Sebastian Kügler committed
276

Frederik Gladhorn's avatar
Frederik Gladhorn committed
277
    QScopedPointer<Edid> edid(new Edid(data));
278
279
280
281
282
283
284
285
    QVERIFY(edid->isValid());

    GetConfigOperation *op = new GetConfigOperation();
    op->exec();
    auto config = op->config();
    QVERIFY(config->outputs().count() > 0);

    auto o = config->outputs().last();
Sebastian Kügler's avatar
Sebastian Kügler committed
286
    qCDebug(KSCREEN_WAYLAND) << "Edid: " << o->edid()->isValid();
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
    QVERIFY(o->edid()->isValid());
    QCOMPARE(o->edid()->deviceId(), edid->deviceId());
    QCOMPARE(o->edid()->name(), edid->name());
    QCOMPARE(o->edid()->vendor(), edid->vendor());
    QCOMPARE(o->edid()->eisaId(), edid->eisaId());
    QCOMPARE(o->edid()->serial(), edid->serial());
    QCOMPARE(o->edid()->hash(), edid->hash());
    QCOMPARE(o->edid()->width(), edid->width());
    QCOMPARE(o->edid()->height(), edid->height());
    QCOMPARE(o->edid()->gamma(), edid->gamma());
    QCOMPARE(o->edid()->red(), edid->red());
    QCOMPARE(o->edid()->green(), edid->green());
    QCOMPARE(o->edid()->blue(), edid->blue());
    QCOMPARE(o->edid()->white(), edid->white());
}

303
304
305
306
307
308
309
310
311
312
void testWaylandBackend::verifyFeatures()
{
    GetConfigOperation *op = new GetConfigOperation();
    op->exec();
    auto config = op->config();
    QVERIFY(!config->supportedFeatures().testFlag(Config::Feature::None));
    QVERIFY(config->supportedFeatures().testFlag(Config::Feature::Writable));
    QVERIFY(!config->supportedFeatures().testFlag(Config::Feature::PrimaryDisplay));
}

313

314
QTEST_GUILESS_MAIN(testWaylandBackend)
315

316
#include "testkwaylandbackend.moc"