File indexing completed on 2024-04-28 05:31:23

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