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"