File indexing completed on 2024-04-14 15:37:32
0001 /* 0002 * SPDX-FileCopyrightText: 2012 Alejandro Fiestas Olivares <afiestas@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include <QObject> 0008 #include <QtTest> 0009 0010 #include "../src/backendmanager_p.h" 0011 #include "../src/config.h" 0012 #include "../src/getconfigoperation.h" 0013 #include "../src/mode.h" 0014 #include "../src/output.h" 0015 #include "../src/screen.h" 0016 #include "../src/setconfigoperation.h" 0017 0018 using namespace KScreen; 0019 0020 class testScreenConfig : public QObject 0021 { 0022 Q_OBJECT 0023 0024 private: 0025 KScreen::ConfigPtr getConfig(); 0026 0027 private Q_SLOTS: 0028 void initTestCase(); 0029 void singleOutput(); 0030 void singleOutputWithoutPreferred(); 0031 void multiOutput(); 0032 void clonesOutput(); 0033 void configCanBeApplied(); 0034 void supportedFeatures(); 0035 void testInvalidMode(); 0036 void cleanupTestCase(); 0037 void testOutputPositionNormalization(); 0038 }; 0039 0040 ConfigPtr testScreenConfig::getConfig() 0041 { 0042 qputenv("KSCREEN_BACKEND_INPROCESS", "1"); 0043 auto *op = new GetConfigOperation(); 0044 if (!op->exec()) { 0045 qWarning("ConfigOperation error: %s", qPrintable(op->errorString())); 0046 BackendManager::instance()->shutdownBackend(); 0047 return ConfigPtr(); 0048 } 0049 0050 BackendManager::instance()->shutdownBackend(); 0051 0052 return op->config(); 0053 } 0054 0055 void testScreenConfig::initTestCase() 0056 { 0057 qputenv("KSCREEN_LOGGING", "false"); 0058 qputenv("KSCREEN_BACKEND", "Fake"); 0059 } 0060 0061 void testScreenConfig::cleanupTestCase() 0062 { 0063 BackendManager::instance()->shutdownBackend(); 0064 } 0065 0066 void testScreenConfig::singleOutput() 0067 { 0068 // json file for the fake backend 0069 KScreen::BackendManager::instance()->setBackendArgs( 0070 {{QStringLiteral("TEST_DATA"), TEST_DATA "singleoutput.json"}, 0071 {QStringLiteral("SUPPORTED_FEATURES"), QVariant::fromValue(KScreen::Config::Feature::PerOutputScaling)}}); 0072 0073 // QVERIFY2(kscreen, KScreen::errorString().toLatin1()); 0074 0075 // QVERIFY2(!kscreen->backend().isEmpty(), "No backend loaded"); 0076 0077 const ConfigPtr config = getConfig(); 0078 QVERIFY(!config.isNull()); 0079 const ScreenPtr screen = config->screen(); 0080 QVERIFY(!screen.isNull()); 0081 0082 QCOMPARE(screen->minSize(), QSize(320, 200)); 0083 QCOMPARE(screen->maxSize(), QSize(8192, 8192)); 0084 QCOMPARE(screen->currentSize(), QSize(1280, 800)); 0085 0086 QCOMPARE(config->outputs().count(), 1); 0087 0088 const OutputPtr output = config->outputs().take(1); 0089 QVERIFY(!output.isNull()); 0090 0091 QCOMPARE(output->name(), QLatin1String("LVDS1")); 0092 QCOMPARE(output->type(), Output::Panel); 0093 QCOMPARE(output->modes().count(), 3); 0094 QCOMPARE(output->pos(), QPoint(0, 0)); 0095 QCOMPARE(output->geometry(), QRect(0, 0, 1280, 800)); 0096 QCOMPARE(output->currentModeId(), QLatin1String("3")); 0097 QCOMPARE(output->preferredModeId(), QLatin1String("3")); 0098 QCOMPARE(output->rotation(), Output::None); 0099 QCOMPARE(output->scale(), 1.0); 0100 QCOMPARE(output->isConnected(), true); 0101 QCOMPARE(output->isEnabled(), true); 0102 QCOMPARE(output->isPrimary(), true); 0103 // QCOMPARE(output->isEmbedded(), true); 0104 QVERIFY2(output->clones().isEmpty(), "In singleOutput is impossible to have clones"); 0105 0106 const ModePtr mode = output->currentMode(); 0107 QCOMPARE(mode->size(), QSize(1280, 800)); 0108 QCOMPARE(mode->refreshRate(), (float)59.9); 0109 } 0110 0111 void testScreenConfig::singleOutputWithoutPreferred() 0112 { 0113 KScreen::BackendManager::instance()->setBackendArgs({{QStringLiteral("TEST_DATA"), TEST_DATA "singleOutputWithoutPreferred.json"}}); 0114 0115 const ConfigPtr config = getConfig(); 0116 QVERIFY(!config.isNull()); 0117 const OutputPtr output = config->outputs().take(1); 0118 QVERIFY(!output.isNull()); 0119 0120 QVERIFY(output->preferredModes().isEmpty()); 0121 QCOMPARE(output->preferredModeId(), QLatin1String("3")); 0122 } 0123 0124 void testScreenConfig::multiOutput() 0125 { 0126 KScreen::BackendManager::instance()->setBackendArgs( 0127 {{QStringLiteral("TEST_DATA"), TEST_DATA "multipleoutput.json"}, 0128 {QStringLiteral("SUPPORTED_FEATURES"), QVariant::fromValue(KScreen::Config::Feature::PerOutputScaling)}}); 0129 0130 const ConfigPtr config = getConfig(); 0131 QVERIFY(!config.isNull()); 0132 const ScreenPtr screen = config->screen(); 0133 QVERIFY(!screen.isNull()); 0134 0135 QCOMPARE(screen->minSize(), QSize(320, 200)); 0136 QCOMPARE(screen->maxSize(), QSize(8192, 8192)); 0137 QCOMPARE(screen->currentSize(), QSize(3200, 1880)); 0138 0139 QCOMPARE(config->outputs().count(), 2); 0140 0141 const OutputPtr output = config->outputs().take(2); 0142 QVERIFY(!output.isNull()); 0143 0144 QCOMPARE(output->name(), QStringLiteral("HDMI1")); 0145 QCOMPARE(output->type(), Output::HDMI); 0146 QCOMPARE(output->modes().count(), 4); 0147 QCOMPARE(output->pos(), QPoint(1280, 0)); 0148 QCOMPARE(output->geometry(), QRect(1280, 0, 1920 / 1.4, 1080 / 1.4)); 0149 QCOMPARE(output->currentModeId(), QLatin1String("4")); 0150 QCOMPARE(output->preferredModeId(), QLatin1String("4")); 0151 QCOMPARE(output->rotation(), Output::None); 0152 QCOMPARE(output->scale(), 1.4); 0153 QCOMPARE(output->isConnected(), true); 0154 QCOMPARE(output->isEnabled(), true); 0155 QCOMPARE(output->isPrimary(), false); 0156 QVERIFY2(output->clones().isEmpty(), "This simulates extended output, no clones"); 0157 0158 const ModePtr mode = output->currentMode(); 0159 QVERIFY(!mode.isNull()); 0160 QCOMPARE(mode->size(), QSize(1920, 1080)); 0161 QCOMPARE(mode->refreshRate(), (float)60.0); 0162 } 0163 0164 void testScreenConfig::clonesOutput() 0165 { 0166 KScreen::BackendManager::instance()->setBackendArgs({{QStringLiteral("TEST_DATA"), TEST_DATA "multipleclone.json"}}); 0167 0168 const ConfigPtr config = getConfig(); 0169 QVERIFY(!config.isNull()); 0170 const ScreenPtr screen = config->screen(); 0171 QVERIFY(!screen.isNull()); 0172 0173 QCOMPARE(screen->minSize(), QSize(320, 200)); 0174 QCOMPARE(screen->maxSize(), QSize(8192, 8192)); 0175 QCOMPARE(screen->currentSize(), QSize(1024, 768)); 0176 0177 const OutputPtr one = config->outputs()[1]; 0178 const OutputPtr two = config->outputs()[2]; 0179 0180 QCOMPARE(one->currentMode()->size(), two->currentMode()->size()); 0181 QCOMPARE(one->clones().count(), 1); 0182 QCOMPARE(one->clones().first(), two->id()); 0183 QVERIFY2(two->clones().isEmpty(), "Output two should have no clones"); 0184 } 0185 0186 void testScreenConfig::configCanBeApplied() 0187 { 0188 KScreen::BackendManager::instance()->setBackendArgs({{QStringLiteral("TEST_DATA"), TEST_DATA "singleoutputBroken.json"}}); 0189 0190 const ConfigPtr brokenConfig = getConfig(); 0191 0192 KScreen::BackendManager::instance()->setBackendArgs({{QStringLiteral("TEST_DATA"), TEST_DATA "singleoutput.json"}}); 0193 0194 const ConfigPtr currentConfig = getConfig(); 0195 QVERIFY(!currentConfig.isNull()); 0196 const OutputPtr primaryBroken = brokenConfig->outputs()[2]; 0197 QVERIFY(!primaryBroken.isNull()); 0198 const OutputPtr currentPrimary = currentConfig->outputs()[1]; 0199 QVERIFY(!currentPrimary.isNull()); 0200 0201 QVERIFY(!Config::canBeApplied(brokenConfig)); 0202 primaryBroken->setId(currentPrimary->id()); 0203 QVERIFY(!Config::canBeApplied(brokenConfig)); 0204 primaryBroken->setConnected(currentPrimary->isConnected()); 0205 QVERIFY(!Config::canBeApplied(brokenConfig)); 0206 primaryBroken->setCurrentModeId(QStringLiteral("42")); 0207 QVERIFY(!Config::canBeApplied(brokenConfig)); 0208 primaryBroken->setCurrentModeId(currentPrimary->currentModeId()); 0209 QVERIFY(!Config::canBeApplied(brokenConfig)); 0210 qDebug() << "brokenConfig.modes" << primaryBroken->mode(QStringLiteral("3")); 0211 primaryBroken->mode(QStringLiteral("3"))->setSize(QSize(1280, 800)); 0212 qDebug() << "brokenConfig.modes" << primaryBroken->mode(QStringLiteral("3")); 0213 QVERIFY(Config::canBeApplied(brokenConfig)); 0214 0215 KScreen::BackendManager::instance()->setBackendArgs({{QStringLiteral("TEST_DATA"), TEST_DATA "tooManyOutputs.json"}}); 0216 0217 const ConfigPtr brokenConfig2 = getConfig(); 0218 QVERIFY(!brokenConfig2.isNull()); 0219 0220 int enabledOutputsCount = 0; 0221 for (const OutputPtr &output : brokenConfig2->outputs()) { 0222 if (output->isEnabled()) { 0223 ++enabledOutputsCount; 0224 } 0225 } 0226 QVERIFY(brokenConfig2->screen()->maxActiveOutputsCount() < enabledOutputsCount); 0227 QVERIFY(!Config::canBeApplied(brokenConfig2)); 0228 0229 const ConfigPtr nulllConfig; 0230 QVERIFY(!Config::canBeApplied(nulllConfig)); 0231 } 0232 0233 void testScreenConfig::supportedFeatures() 0234 { 0235 ConfigPtr config = getConfig(); 0236 0237 QVERIFY(config->supportedFeatures().testFlag(KScreen::Config::Feature::None)); 0238 QVERIFY(!config->supportedFeatures().testFlag(KScreen::Config::Feature::Writable)); 0239 QVERIFY(!config->supportedFeatures().testFlag(KScreen::Config::Feature::PrimaryDisplay)); 0240 QVERIFY(!config->supportedFeatures().testFlag(KScreen::Config::Feature::PerOutputScaling)); 0241 0242 config->setSupportedFeatures(KScreen::Config::Feature::Writable | KScreen::Config::Feature::PrimaryDisplay); 0243 QVERIFY(config->supportedFeatures().testFlag(KScreen::Config::Feature::Writable)); 0244 QVERIFY(config->supportedFeatures().testFlag(KScreen::Config::Feature::PrimaryDisplay)); 0245 0246 config->setSupportedFeatures(KScreen::Config::Feature::None); 0247 QVERIFY(config->supportedFeatures().testFlag(KScreen::Config::Feature::None)); 0248 0249 config->setSupportedFeatures(KScreen::Config::Feature::PerOutputScaling | KScreen::Config::Feature::Writable); 0250 QVERIFY(!config->supportedFeatures().testFlag(KScreen::Config::Feature::None)); 0251 QVERIFY(config->supportedFeatures().testFlag(KScreen::Config::Feature::Writable)); 0252 QVERIFY(config->supportedFeatures().testFlag(KScreen::Config::Feature::PerOutputScaling)); 0253 0254 config->setSupportedFeatures(KScreen::Config::Feature::PerOutputScaling | KScreen::Config::Feature::Writable | KScreen::Config::Feature::PrimaryDisplay); 0255 QVERIFY(!config->supportedFeatures().testFlag(KScreen::Config::Feature::None)); 0256 QVERIFY(config->supportedFeatures().testFlag(KScreen::Config::Feature::Writable)); 0257 QVERIFY(config->supportedFeatures().testFlag(KScreen::Config::Feature::PrimaryDisplay)); 0258 QVERIFY(config->supportedFeatures().testFlag(KScreen::Config::Feature::PerOutputScaling)); 0259 } 0260 0261 void testScreenConfig::testInvalidMode() 0262 { 0263 ModeList modes; 0264 ModePtr invalidMode = modes.value(QStringLiteral("99")); 0265 QVERIFY(invalidMode.isNull()); 0266 0267 auto output = new KScreen::Output(); 0268 auto currentMode = output->currentMode(); 0269 QVERIFY(currentMode.isNull()); 0270 QVERIFY(!currentMode); 0271 delete output; 0272 } 0273 0274 void testScreenConfig::testOutputPositionNormalization() 0275 { 0276 KScreen::BackendManager::instance()->setBackendArgs({{QStringLiteral("TEST_DATA"), TEST_DATA "multipleoutput.json"}}); 0277 0278 const ConfigPtr config = getConfig(); 0279 QVERIFY(!config.isNull()); 0280 auto left = config->outputs().first(); 0281 auto right = config->outputs().last(); 0282 QVERIFY(!left.isNull()); 0283 QVERIFY(!right.isNull()); 0284 left->setPos(QPoint(-5000, 700)); 0285 right->setPos(QPoint(-3720, 666)); 0286 QCOMPARE(left->pos(), QPoint(-5000, 700)); 0287 QCOMPARE(right->pos(), QPoint(-3720, 666)); 0288 0289 // start a set operation to fix up the positions 0290 { 0291 auto setop = new SetConfigOperation(config); 0292 setop->exec(); 0293 } 0294 QCOMPARE(left->pos(), QPoint(0, 34)); 0295 QCOMPARE(right->pos(), QPoint(1280, 0)); 0296 0297 // make sure it doesn't touch a valid config 0298 { 0299 auto setop = new SetConfigOperation(config); 0300 setop->exec(); 0301 } 0302 QCOMPARE(left->pos(), QPoint(0, 34)); 0303 QCOMPARE(right->pos(), QPoint(1280, 0)); 0304 0305 // positions of single outputs should be at 0, 0 0306 left->setEnabled(false); 0307 { 0308 auto setop = new SetConfigOperation(config); 0309 setop->exec(); 0310 } 0311 QCOMPARE(right->pos(), QPoint()); 0312 } 0313 0314 QTEST_MAIN(testScreenConfig) 0315 0316 #include "testscreenconfig.moc"