File indexing completed on 2024-04-21 16:17:28

0001 /*
0002  *  SPDX-FileCopyrightText: 2012 Alejandro Fiestas Olivares <afiestas@kde.org>
0003  *  SPDX-FileCopyrightText: 2012 Sebastian Kügler <sebas@kde.org>
0004  *
0005  *  SPDX-License-Identifier: LGPL-2.1-or-later
0006  */
0007 
0008 #include <QElapsedTimer>
0009 #include <QObject>
0010 #include <QtTest>
0011 
0012 #include <cstdint>
0013 
0014 #include "../src/backendmanager_p.h"
0015 #include "../src/config.h"
0016 #include "../src/edid.h"
0017 #include "../src/getconfigoperation.h"
0018 #include "../src/mode.h"
0019 #include "../src/output.h"
0020 #include "../src/screen.h"
0021 
0022 Q_LOGGING_CATEGORY(KSCREEN_QSCREEN, "kscreen.qscreen")
0023 
0024 using namespace KScreen;
0025 
0026 class testQScreenBackend : public QObject
0027 {
0028     Q_OBJECT
0029 
0030 private Q_SLOTS:
0031     void initTestCase();
0032     void verifyConfig();
0033     void verifyScreen();
0034     void verifyOutputs();
0035     void verifyModes();
0036     void verifyFeatures();
0037     void commonUsagePattern();
0038     void cleanupTestCase();
0039 
0040 private:
0041     QProcess m_process;
0042     ConfigPtr m_config;
0043     QString m_backend;
0044 };
0045 
0046 void testQScreenBackend::initTestCase()
0047 {
0048     qputenv("KSCREEN_LOGGING", "false");
0049     qputenv("KSCREEN_BACKEND", "qscreen");
0050     qputenv("KSCREEN_BACKEND_INPROCESS", "1");
0051     KScreen::BackendManager::instance()->shutdownBackend();
0052 
0053     m_backend = QString::fromLocal8Bit(qgetenv("KSCREEN_BACKEND"));
0054 
0055     QElapsedTimer t;
0056     t.start();
0057     auto *op = new GetConfigOperation();
0058     op->exec();
0059     m_config = op->config();
0060     const int n = t.nsecsElapsed();
0061     qDebug() << "Test took: " << n << "ns";
0062 }
0063 
0064 void testQScreenBackend::verifyConfig()
0065 {
0066     QVERIFY(!m_config.isNull());
0067     if (!m_config) {
0068         QSKIP("QScreenbackend invalid", SkipAll);
0069     }
0070 }
0071 
0072 void testQScreenBackend::verifyScreen()
0073 {
0074     ScreenPtr screen = m_config->screen();
0075 
0076     QVERIFY(screen->minSize().width() <= screen->maxSize().width());
0077     QVERIFY(screen->minSize().height() <= screen->maxSize().height());
0078 
0079     QVERIFY(screen->minSize().width() <= screen->currentSize().width());
0080     QVERIFY(screen->minSize().height() <= screen->currentSize().height());
0081 
0082     QVERIFY(screen->maxSize().width() >= screen->currentSize().width());
0083     QVERIFY(screen->maxSize().height() >= screen->currentSize().height());
0084     QVERIFY(m_config->screen()->maxActiveOutputsCount() > 0);
0085 }
0086 
0087 void testQScreenBackend::verifyOutputs()
0088 {
0089     bool primaryFound = false;
0090     for (const KScreen::OutputPtr &op : m_config->outputs()) {
0091         if (op->isPrimary()) {
0092             primaryFound = true;
0093         }
0094     }
0095     qDebug() << "Primary found? " << primaryFound;
0096     QVERIFY(primaryFound);
0097     if (m_backend == QLatin1String("screen")) {
0098         QCOMPARE(m_config->outputs().count(), QGuiApplication::screens().count());
0099     }
0100 
0101     const KScreen::OutputPtr primary = m_config->primaryOutput();
0102     QVERIFY(primary->isEnabled());
0103     QVERIFY(primary->isConnected());
0104     // qDebug() << "Primary geometry? " << primary->geometry();
0105     // qDebug() << " prim modes: " << primary->modes();
0106 
0107     QList<int> ids;
0108     for (const KScreen::OutputPtr &output : m_config->outputs()) {
0109         qDebug() << " _____________________ Output: " << output;
0110         qDebug() << "   output name: " << output->name();
0111         qDebug() << "   output modes: " << output->modes().count() << output->modes();
0112         qDebug() << "   output enabled: " << output->isEnabled();
0113         qDebug() << "   output connect: " << output->isConnected();
0114         qDebug() << "   output sizeMm : " << output->sizeMm();
0115         QVERIFY(!output->name().isEmpty());
0116         QVERIFY(output->id() > -1);
0117         QVERIFY(output->isConnected());
0118         QVERIFY(output->isEnabled());
0119         QVERIFY(output->geometry() != QRectF(1, 1, 1, 1));
0120         QVERIFY(output->geometry() != QRectF());
0121 
0122         // Pass, but leave a note, when the x server doesn't report physical size
0123         if (!output->sizeMm().isValid()) {
0124             QEXPECT_FAIL("", "The X server doesn't return a sensible physical output size", Continue);
0125             QVERIFY(output->sizeMm() != QSize());
0126         }
0127         QVERIFY(output->edid() != nullptr);
0128         QCOMPARE(output->rotation(), Output::None);
0129         QVERIFY(!ids.contains(output->id()));
0130         ids << output->id();
0131     }
0132 }
0133 
0134 void testQScreenBackend::verifyModes()
0135 {
0136     const KScreen::OutputPtr primary = m_config->primaryOutput();
0137     QVERIFY(primary);
0138     QVERIFY(primary->modes().count() > 0);
0139 
0140     for (const KScreen::OutputPtr &output : m_config->outputs()) {
0141         for (const KScreen::ModePtr &mode : output->modes()) {
0142             qDebug() << "   Mode   : " << mode->name();
0143             QVERIFY(!mode->name().isEmpty());
0144             QVERIFY(mode->refreshRate() > 0);
0145             QVERIFY(mode->size() != QSize());
0146         }
0147     }
0148 }
0149 
0150 void testQScreenBackend::commonUsagePattern()
0151 {
0152     auto *op = new GetConfigOperation();
0153     op->exec();
0154 
0155     const KScreen::OutputList outputs = op->config()->outputs();
0156 
0157     QVariantList outputList;
0158     for (const KScreen::OutputPtr &output : outputs) {
0159         if (!output->isConnected()) {
0160             continue;
0161         }
0162 
0163         QVariantMap info;
0164         info[QStringLiteral("id")] = output->id();
0165         info[QStringLiteral("priority")] = output->priority();
0166         info[QStringLiteral("enabled")] = output->isEnabled();
0167         info[QStringLiteral("rotation")] = output->rotation();
0168 
0169         QVariantMap pos;
0170         pos[QStringLiteral("x")] = output->pos().x();
0171         pos[QStringLiteral("y")] = output->pos().y();
0172         info[QStringLiteral("pos")] = pos;
0173 
0174         if (output->isEnabled()) {
0175             const KScreen::ModePtr mode = output->currentMode();
0176             if (!mode) {
0177                 // qWarning() << "CurrentMode is null" << output->name();
0178                 return;
0179             }
0180 
0181             QVariantMap modeInfo;
0182             modeInfo[QStringLiteral("refresh")] = mode->refreshRate();
0183 
0184             QVariantMap modeSize;
0185             modeSize[QStringLiteral("width")] = mode->size().width();
0186             modeSize[QStringLiteral("height")] = mode->size().height();
0187             modeInfo[QStringLiteral("size")] = modeSize;
0188 
0189             info[QStringLiteral("mode")] = modeInfo;
0190         }
0191 
0192         outputList.append(info);
0193     }
0194 }
0195 
0196 void testQScreenBackend::cleanupTestCase()
0197 {
0198     KScreen::BackendManager::instance()->shutdownBackend();
0199     qApp->exit(0);
0200 }
0201 
0202 void testQScreenBackend::verifyFeatures()
0203 {
0204     GetConfigOperation *op = new GetConfigOperation();
0205     op->exec();
0206     auto config = op->config();
0207     QVERIFY(config->supportedFeatures().testFlag(Config::Feature::None));
0208     QVERIFY(!config->supportedFeatures().testFlag(Config::Feature::Writable));
0209     QVERIFY(!config->supportedFeatures().testFlag(Config::Feature::PrimaryDisplay));
0210 }
0211 
0212 QTEST_MAIN(testQScreenBackend)
0213 
0214 #include "testqscreenbackend.moc"