File indexing completed on 2024-03-24 17:07:36

0001 /*
0002  *  SPDX-FileCopyrightText: 2014-2015 Sebastian Kügler <sebas@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.1-or-later
0005  */
0006 
0007 #include <QCoreApplication>
0008 #include <QCryptographicHash>
0009 #include <QObject>
0010 #include <QtTest>
0011 
0012 #include "../src/backendmanager_p.h"
0013 #include "../src/config.h"
0014 #include "../src/configmonitor.h"
0015 #include "../src/edid.h"
0016 #include "../src/getconfigoperation.h"
0017 #include "../src/mode.h"
0018 #include "../src/output.h"
0019 #include "../src/screen.h"
0020 #include "../src/setconfigoperation.h"
0021 
0022 // KWayland
0023 #include <KWayland/Server/display.h>
0024 #include <KWayland/Server/outputdevice_interface.h>
0025 
0026 #include "waylandtestserver.h"
0027 
0028 Q_LOGGING_CATEGORY(KSCREEN_WAYLAND, "kscreen.kwayland")
0029 
0030 using namespace KScreen;
0031 
0032 class testWaylandBackend : public QObject
0033 {
0034     Q_OBJECT
0035 
0036 public:
0037     explicit testWaylandBackend(QObject *parent = nullptr);
0038 
0039 private Q_SLOTS:
0040     void initTestCase();
0041     void cleanupTestCase();
0042     void loadConfig();
0043 
0044     void verifyConfig();
0045     void verifyOutputs();
0046     void verifyModes();
0047     void verifyScreen();
0048     void verifyIds();
0049     void verifyFeatures();
0050     void simpleWrite();
0051     void addOutput();
0052     void removeOutput();
0053     void testEdid();
0054 
0055 private:
0056     ConfigPtr m_config;
0057     WaylandTestServer *m_server;
0058     KWayland::Server::OutputDeviceInterface *m_serverOutputDevice;
0059 };
0060 
0061 testWaylandBackend::testWaylandBackend(QObject *parent)
0062     : QObject(parent)
0063     , m_config(nullptr)
0064 {
0065     qputenv("KSCREEN_LOGGING", "false");
0066     m_server = new WaylandTestServer(this);
0067     m_server->setConfig(QLatin1String(TEST_DATA) + QLatin1String("multipleoutput.json"));
0068 }
0069 
0070 void testWaylandBackend::initTestCase()
0071 {
0072     qputenv("KSCREEN_BACKEND", "kwayland");
0073     KScreen::BackendManager::instance()->shutdownBackend();
0074     // This is how KWayland will pick up the right socket,
0075     // and thus connect to our internal test server.
0076     setenv("WAYLAND_DISPLAY", s_socketName.toLocal8Bit().constData(), 1);
0077     m_server->start();
0078 
0079     GetConfigOperation *op = new GetConfigOperation();
0080     op->exec();
0081     m_config = op->config();
0082 }
0083 
0084 void testWaylandBackend::loadConfig()
0085 {
0086     GetConfigOperation *op = new GetConfigOperation();
0087     op->exec();
0088     m_config = op->config();
0089     QVERIFY(m_config->isValid());
0090     qCDebug(KSCREEN_WAYLAND) << "ops" << m_config->outputs();
0091 }
0092 
0093 void testWaylandBackend::verifyConfig()
0094 {
0095     QVERIFY(m_config != nullptr);
0096     if (!m_config) {
0097         QSKIP("Wayland backend invalid", SkipAll);
0098     }
0099 }
0100 
0101 void testWaylandBackend::verifyScreen()
0102 {
0103     ScreenPtr screen = m_config->screen();
0104 
0105     QVERIFY(screen->minSize().width() <= screen->maxSize().width());
0106     QVERIFY(screen->minSize().height() <= screen->maxSize().height());
0107 
0108     QVERIFY(screen->minSize().width() <= screen->currentSize().width());
0109     QVERIFY(screen->minSize().height() <= screen->currentSize().height());
0110 
0111     QVERIFY(screen->maxSize().width() >= screen->currentSize().width());
0112     QVERIFY(screen->maxSize().height() >= screen->currentSize().height());
0113     QVERIFY(m_config->screen()->maxActiveOutputsCount() > 0);
0114 }
0115 
0116 void testWaylandBackend::verifyOutputs()
0117 {
0118     bool primaryFound = false;
0119     for (const KScreen::OutputPtr &op : m_config->outputs()) {
0120         if (op->isPrimary()) {
0121             primaryFound = true;
0122         }
0123     }
0124     // qCDebug(KSCREEN_WAYLAND) << "Primary found? " << primaryFound << m_config->outputs();
0125     QVERIFY(primaryFound);
0126     QVERIFY(m_config->outputs().count());
0127     QCOMPARE(m_server->outputCount(), m_config->outputs().count());
0128 
0129     KScreen::OutputPtr primary = m_config->primaryOutput();
0130     QVERIFY(primary->isEnabled());
0131     QVERIFY(primary->isConnected());
0132 
0133     QList<int> ids;
0134     for (const auto &output : m_config->outputs()) {
0135         QVERIFY(!output->name().isEmpty());
0136         QVERIFY(output->id() > -1);
0137         QVERIFY(output->isConnected());
0138         QVERIFY(output->geometry() != QRectF(1, 1, 1, 1));
0139         QVERIFY(output->geometry() != QRectF());
0140         QVERIFY(output->sizeMm() != QSize());
0141         QVERIFY(output->edid() != nullptr);
0142         QVERIFY(output->preferredModes().size() == 1);
0143         QCOMPARE(output->rotation(), Output::None);
0144         QVERIFY(!ids.contains(output->id()));
0145         ids << output->id();
0146     }
0147 }
0148 
0149 void testWaylandBackend::verifyModes()
0150 {
0151     KScreen::OutputPtr primary = m_config->primaryOutput();
0152     QVERIFY(primary);
0153     QVERIFY(primary->modes().count() > 0);
0154 
0155     for (const auto &output : m_config->outputs()) {
0156         for (const auto &mode : output->modes()) {
0157             QVERIFY(!mode->name().isEmpty());
0158             QVERIFY(mode->refreshRate() > 0);
0159             QVERIFY(mode->size().isValid());
0160         }
0161     }
0162 }
0163 
0164 void testWaylandBackend::verifyIds()
0165 {
0166     QList<quint32> ids;
0167     for (const auto &output : m_config->outputs()) {
0168         QVERIFY(ids.contains(output->id()) == false);
0169         QVERIFY(output->id() > 0);
0170         ids << output->id();
0171     }
0172 }
0173 
0174 void testWaylandBackend::simpleWrite()
0175 {
0176     KScreen::BackendManager::instance()->shutdownBackend();
0177     GetConfigOperation *op = new GetConfigOperation();
0178     op->exec();
0179     m_config = op->config();
0180     auto output = m_config->output(3);
0181     QVERIFY(output);
0182     auto n_mode = QStringLiteral("800x600@60");
0183     auto o_mode = output->currentModeId();
0184     output->setCurrentModeId(n_mode);
0185 
0186     auto setop = new SetConfigOperation(m_config);
0187     QVERIFY(setop->exec());
0188 }
0189 
0190 void testWaylandBackend::cleanupTestCase()
0191 {
0192     m_config->deleteLater();
0193     KScreen::BackendManager::instance()->shutdownBackend();
0194 }
0195 
0196 void testWaylandBackend::addOutput()
0197 {
0198     KScreen::BackendManager::instance()->shutdownBackend();
0199     GetConfigOperation *op = new GetConfigOperation();
0200     op->exec();
0201     auto config = op->config();
0202     QCOMPARE(config->outputs().count(), 2);
0203     KScreen::ConfigMonitor *monitor = KScreen::ConfigMonitor::instance();
0204     monitor->addConfig(config);
0205     QSignalSpy configSpy(monitor, &KScreen::ConfigMonitor::configurationChanged);
0206 
0207     // Now add an outputdevice on the server side
0208     m_serverOutputDevice = m_server->display()->createOutputDevice(this);
0209     m_serverOutputDevice->setUuid("1337");
0210 
0211     OutputDeviceInterface::Mode m0;
0212     m0.id = 0;
0213     m0.size = QSize(800, 600);
0214     m0.flags = OutputDeviceInterface::ModeFlags(OutputDeviceInterface::ModeFlag::Preferred);
0215     m_serverOutputDevice->addMode(m0);
0216 
0217     OutputDeviceInterface::Mode m1;
0218     m1.id = 1;
0219     m1.size = QSize(1024, 768);
0220     m_serverOutputDevice->addMode(m1);
0221 
0222     OutputDeviceInterface::Mode m2;
0223     m2.id = 2;
0224     m2.size = QSize(1280, 1024);
0225     m2.refreshRate = 90000;
0226     m_serverOutputDevice->addMode(m2);
0227 
0228     m_serverOutputDevice->setCurrentMode(1);
0229 
0230     m_serverOutputDevice->create();
0231 
0232     QVERIFY(configSpy.wait());
0233     // QTRY_VERIFY(configSpy.count());
0234 
0235     GetConfigOperation *op2 = new GetConfigOperation();
0236     op2->exec();
0237     auto newconfig = op2->config();
0238     QCOMPARE(newconfig->outputs().count(), 3);
0239 }
0240 
0241 void testWaylandBackend::removeOutput()
0242 {
0243     KScreen::BackendManager::instance()->shutdownBackend();
0244     GetConfigOperation *op = new GetConfigOperation();
0245     op->exec();
0246     auto config = op->config();
0247     QCOMPARE(config->outputs().count(), 3);
0248     KScreen::ConfigMonitor *monitor = KScreen::ConfigMonitor::instance();
0249     monitor->addConfig(config);
0250     QSignalSpy configSpy(monitor, &KScreen::ConfigMonitor::configurationChanged);
0251 
0252     delete m_serverOutputDevice;
0253     QVERIFY(configSpy.wait());
0254     GetConfigOperation *op2 = new GetConfigOperation();
0255     op2->exec();
0256     auto newconfig = op2->config();
0257     QCOMPARE(newconfig->outputs().count(), 2);
0258 }
0259 
0260 void testWaylandBackend::testEdid()
0261 {
0262     m_server->showOutputs();
0263 
0264     QByteArray data = QByteArray::fromBase64(
0265         "AP///////wAQrBbwTExLQQ4WAQOANCB46h7Frk80sSYOUFSlSwCBgKlA0QBxTwEBAQEBAQEBKDyAoHCwI0AwIDYABkQhAAAaAAAA/wBGNTI1TTI0NUFLTEwKAAAA/ABERUxMIFUyNDEwCiAgAAAA/"
0266         "QA4TB5REQAKICAgICAgAToCAynxUJAFBAMCBxYBHxITFCAVEQYjCQcHZwMMABAAOC2DAQAA4wUDAQI6gBhxOC1AWCxFAAZEIQAAHgEdgBhxHBYgWCwlAAZEIQAAngEdAHJR0B4gbihVAAZEIQAAHow"
0267         "K0Iog4C0QED6WAAZEIQAAGAAAAAAAAAAAAAAAAAAAPg==");
0268 
0269     QScopedPointer<Edid> edid(new Edid(data));
0270     QVERIFY(edid->isValid());
0271 
0272     GetConfigOperation *op = new GetConfigOperation();
0273     op->exec();
0274     auto config = op->config();
0275     QVERIFY(config->outputs().count() > 0);
0276 
0277     auto o = config->outputs().last();
0278     qCDebug(KSCREEN_WAYLAND) << "Edid: " << o->edid()->isValid();
0279     QVERIFY(o->edid()->isValid());
0280     QCOMPARE(o->edid()->deviceId(), edid->deviceId());
0281     QCOMPARE(o->edid()->name(), edid->name());
0282     QCOMPARE(o->edid()->vendor(), edid->vendor());
0283     QCOMPARE(o->edid()->eisaId(), edid->eisaId());
0284     QCOMPARE(o->edid()->serial(), edid->serial());
0285     QCOMPARE(o->edid()->hash(), edid->hash());
0286     QCOMPARE(o->edid()->width(), edid->width());
0287     QCOMPARE(o->edid()->height(), edid->height());
0288     QCOMPARE(o->edid()->gamma(), edid->gamma());
0289     QCOMPARE(o->edid()->red(), edid->red());
0290     QCOMPARE(o->edid()->green(), edid->green());
0291     QCOMPARE(o->edid()->blue(), edid->blue());
0292     QCOMPARE(o->edid()->white(), edid->white());
0293 }
0294 
0295 void testWaylandBackend::verifyFeatures()
0296 {
0297     GetConfigOperation *op = new GetConfigOperation();
0298     op->exec();
0299     auto config = op->config();
0300     QVERIFY(!config->supportedFeatures().testFlag(Config::Feature::None));
0301     QVERIFY(config->supportedFeatures().testFlag(Config::Feature::Writable));
0302     QVERIFY(!config->supportedFeatures().testFlag(Config::Feature::PrimaryDisplay));
0303 }
0304 
0305 QTEST_GUILESS_MAIN(testWaylandBackend)
0306 
0307 #include "testkwaylandbackend.moc"