File indexing completed on 2025-01-26 05:06:20
0001 /* 0002 SPDX-FileCopyrightText: 2017 Klarälvdalens Datakonsult AB a KDAB Group company <info@kdab.com> 0003 0004 Work sponsored by the LiMux project of the city of Munich. 0005 SPDX-FileContributor: Andras Mantia <andras.mantia@kdab.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include <array> 0010 0011 #include "screenmapper.h" 0012 #include "screenmappertest.h" 0013 0014 #include <QSignalSpy> 0015 #include <QTest> 0016 0017 #include <PlasmaActivities/Consumer> 0018 0019 using namespace Qt::StringLiterals; 0020 0021 QTEST_MAIN(ScreenMapperTest) 0022 0023 void ScreenMapperTest::initTestCase() 0024 { 0025 m_screenMapper = ScreenMapper::instance(); 0026 m_currentActivity = KActivities::Consumer().currentActivity(); 0027 m_alternativeActivity = QStringLiteral("a779f58a-b5e3-426d-9994-a8c54d26d528"); // Generated by uuidgen 0028 Q_ASSERT(m_currentActivity != m_alternativeActivity); 0029 } 0030 0031 void ScreenMapperTest::init() 0032 { 0033 m_screenMapper->cleanup(); 0034 } 0035 0036 void ScreenMapperTest::tst_addScreens() 0037 { 0038 const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); 0039 QSignalSpy s(m_screenMapper, &ScreenMapper::screensChanged); 0040 m_screenMapper->addScreen(-1, m_currentActivity, path); 0041 QCOMPARE(s.count(), 0); 0042 m_screenMapper->addScreen(1, m_currentActivity, path); 0043 QCOMPARE(s.count(), 1); 0044 m_screenMapper->addScreen(0, m_currentActivity, path); 0045 QCOMPARE(s.count(), 2); 0046 m_screenMapper->addScreen(1, m_currentActivity, path); 0047 QCOMPARE(s.count(), 2); 0048 0049 // Test if activity ID works 0050 m_screenMapper->addScreen(1, m_alternativeActivity, path); 0051 QCOMPARE(s.count(), 3); 0052 m_screenMapper->addScreen(3, m_alternativeActivity, path); 0053 QCOMPARE(s.count(), 4); 0054 0055 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 0); 0056 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_alternativeActivity), 1); 0057 } 0058 0059 void ScreenMapperTest::tst_removeScreens() 0060 { 0061 const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); 0062 addScreens(path, m_currentActivity); 0063 addScreens(path, m_alternativeActivity); 0064 QSignalSpy s(m_screenMapper, &ScreenMapper::screensChanged); 0065 m_screenMapper->removeScreen(-1, m_currentActivity, path); 0066 QCOMPARE(s.count(), 0); 0067 m_screenMapper->removeScreen(1, m_currentActivity, path); 0068 QCOMPARE(s.count(), 1); 0069 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 0); 0070 m_screenMapper->removeScreen(1, m_currentActivity, path); 0071 QCOMPARE(s.count(), 1); 0072 m_screenMapper->addScreen(3, m_currentActivity, path); 0073 QCOMPARE(s.count(), 2); 0074 m_screenMapper->removeScreen(0, m_currentActivity, path); 0075 QCOMPARE(s.count(), 3); 0076 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 2); 0077 0078 // Remove screens on m_currentActivity should not affect screens on m_alternativeActivity 0079 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_alternativeActivity), 0); 0080 m_screenMapper->removeScreen(2, m_alternativeActivity, path); 0081 QCOMPARE(s.count(), 4); 0082 0083 // Remove screens on m_alternativeActivity should not affect screens on m_currentActivity 0084 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 2); 0085 } 0086 0087 void ScreenMapperTest::tst_addMapping() 0088 { 0089 const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); 0090 addScreens(path, m_currentActivity); 0091 addScreens(path, m_alternativeActivity); 0092 QSignalSpy s(m_screenMapper, &ScreenMapper::screenMappingChanged); 0093 QString file(QStringLiteral("desktop:/foo%1.txt")); 0094 0095 for (int i = 0; i < 3; i++) { 0096 const QUrl url = ScreenMapper::stringToUrl(file.arg(i)); 0097 m_screenMapper->addMapping(url, i, m_currentActivity); 0098 QCOMPARE(s.count(), i + 1); 0099 QCOMPARE(m_screenMapper->screenForItem(url, m_currentActivity), i); 0100 0101 // Mappings added to m_currentActivity should not affect mappings on m_alternativeActivity 0102 QCOMPARE(m_screenMapper->screenForItem(url, m_alternativeActivity), -1); 0103 } 0104 } 0105 0106 void ScreenMapperTest::tst_addRemoveScreenWithItems() 0107 { 0108 const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); 0109 addScreens(path, m_currentActivity); 0110 addScreens(path, m_alternativeActivity); 0111 QString file(QStringLiteral("desktop:/foo%1.txt")); 0112 0113 for (int i = 0; i < 3; i++) { 0114 const QUrl url = ScreenMapper::stringToUrl(file.arg(i)); 0115 for (const QString &activity : {m_currentActivity, m_alternativeActivity}) { 0116 m_screenMapper->addMapping(url, i, activity); 0117 } 0118 } 0119 0120 // remove one screen 0121 m_screenMapper->removeScreen(1, m_currentActivity, path); 0122 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(0)), m_currentActivity), 0); 0123 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_currentActivity), -1); 0124 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(2)), m_currentActivity), 2); 0125 // Remove a screen of m_currentActivity should not affect screens of m_alternativeActivity 0126 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_alternativeActivity), 1); 0127 0128 // add removed screen back, items screen is restored 0129 m_screenMapper->addScreen(1, m_currentActivity, path); 0130 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(0)), m_currentActivity), 0); 0131 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_currentActivity), 1); 0132 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(2)), m_currentActivity), 2); 0133 // Restore a screen of m_currentActivity should not affect screens of m_alternativeActivity 0134 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_alternativeActivity), 1); 0135 0136 // remove all screens, firstAvailableScreen changes 0137 m_screenMapper->removeScreen(0, m_currentActivity, path); 0138 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 1); 0139 m_screenMapper->removeScreen(1, m_currentActivity, path); 0140 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 2); 0141 m_screenMapper->removeScreen(2, m_currentActivity, path); 0142 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), -1); 0143 // Remove screens of m_currentActivity should not affect screens of m_alternativeActivity 0144 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_alternativeActivity), 0); 0145 0146 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(0)), m_currentActivity), -1); 0147 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_currentActivity), -1); 0148 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(2)), m_currentActivity), -1); 0149 0150 // add all screens back, all item's screen is restored 0151 addScreens(path, m_currentActivity); 0152 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(0)), m_currentActivity), 0); 0153 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_currentActivity), 1); 0154 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(2)), m_currentActivity), 2); 0155 0156 // remove one screen and move its item 0157 const QUrl movedItem = ScreenMapper::stringToUrl(file.arg(1)); 0158 m_screenMapper->removeScreen(1, m_currentActivity, path); 0159 QCOMPARE(m_screenMapper->screenForItem(movedItem, m_currentActivity), -1); 0160 m_screenMapper->addMapping(movedItem, 0, m_currentActivity); 0161 QCOMPARE(m_screenMapper->screenForItem(movedItem, m_currentActivity), 0); 0162 QCOMPARE(m_screenMapper->screenForItem(movedItem, m_alternativeActivity), 1); 0163 0164 // add back the screen, item goes back to the original place 0165 m_screenMapper->addScreen(1, m_currentActivity, path); 0166 QCOMPARE(m_screenMapper->screenForItem(movedItem, m_currentActivity), 1); 0167 QCOMPARE(m_screenMapper->screenForItem(movedItem, m_alternativeActivity), 1); 0168 } 0169 0170 void ScreenMapperTest::tst_addRemoveScreenDifferentPaths() 0171 { 0172 const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/Foo")); 0173 const auto path2 = ScreenMapper::stringToUrl(QStringLiteral("desktop:/Foo2")); 0174 m_screenMapper->addScreen(0, m_currentActivity, path); 0175 QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 0); 0176 QCOMPARE(m_screenMapper->firstAvailableScreen(path2, m_currentActivity), -1); 0177 } 0178 0179 void ScreenMapperTest::tst_readScreenActivityMapping() 0180 { 0181 const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); 0182 addScreens(path, m_currentActivity); 0183 addScreens(path, m_alternativeActivity); 0184 0185 QString file(QStringLiteral("desktop:/foo%1.txt")); 0186 const QStringList paths{ 0187 file.arg(0), 0188 file.arg(1), 0189 }; 0190 // clang-format off 0191 const QStringList mapping{ 0192 paths[0], "0"_L1, m_currentActivity, 0193 paths[1], "1"_L1, m_currentActivity, 0194 paths[0], "1"_L1, m_alternativeActivity, 0195 }; 0196 // clang-format on 0197 QSignalSpy s(m_screenMapper, &ScreenMapper::screenMappingChanged); 0198 0199 m_screenMapper->setScreenMapping(mapping); 0200 QCOMPARE(s.count(), 1); 0201 0202 // Check if the config is loaded correctly 0203 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[0]), m_currentActivity), 0); 0204 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[1]), m_currentActivity), 1); 0205 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[0]), m_alternativeActivity), 1); 0206 QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[1]), m_alternativeActivity), -1); 0207 } 0208 0209 void ScreenMapperTest::tst_saveScreenActivityMapping() 0210 { 0211 const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); 0212 addScreens(path, m_currentActivity); 0213 addScreens(path, m_alternativeActivity); 0214 0215 QString file(QStringLiteral("desktop:/foo%1.txt")); 0216 const std::array<QStringList, 3> expectedMapping{ 0217 QStringList{file.arg(0), "0"_L1, m_currentActivity}, 0218 QStringList{file.arg(1), "1"_L1, m_currentActivity}, 0219 QStringList{file.arg(0), "1"_L1, m_alternativeActivity}, 0220 }; 0221 0222 for (const auto &l : expectedMapping) { 0223 m_screenMapper->addMapping(ScreenMapper::stringToUrl(l[0]), l[1].toInt(), l[2]); 0224 } 0225 0226 const QStringList mapping = m_screenMapper->screenMapping(); 0227 0228 QCOMPARE(mapping.count(), expectedMapping.size() * expectedMapping[0].size()); 0229 0230 for (int i = 0; i < mapping.count() - (expectedMapping[0].size() - 1); i += expectedMapping[0].size()) { 0231 const QStringList configGroup{mapping[i], mapping[i + 1], mapping[i + 2]}; 0232 QVERIFY(std::find(std::cbegin(expectedMapping), std::cend(expectedMapping), configGroup) != std::cend(expectedMapping)); 0233 } 0234 } 0235 0236 void ScreenMapperTest::tst_readAndSaveItemsOnActivitiesOnDisabledScreens() 0237 { 0238 QString file(QStringLiteral("desktop:/foo%1.txt")); 0239 const QStringList paths{ 0240 ScreenMapper::stringToUrl(file.arg(0)).toString(), 0241 ScreenMapper::stringToUrl(file.arg(1)).toString(), 0242 ScreenMapper::stringToUrl(file.arg(2)).toString(), 0243 ScreenMapper::stringToUrl(file.arg(3)).toString(), 0244 }; 0245 // clang-format off 0246 const std::array<QStringList, 3> expectedMapping{ 0247 QStringList{"0"_L1, m_currentActivity, "2"_L1, paths[0], paths[1]}, 0248 QStringList{"1"_L1, m_currentActivity, "2"_L1, paths[2], paths[3]}, 0249 QStringList{"0"_L1, m_alternativeActivity, "2"_L1, paths[0], paths[1]}, 0250 }; 0251 // clang-format on 0252 QStringList seralizedMap; 0253 0254 // Create a seralized QStringList from expectedMapping 0255 for (const auto &l : expectedMapping) { 0256 for (const auto &s : l) { 0257 seralizedMap.append(s); 0258 } 0259 } 0260 0261 m_screenMapper->readDisabledScreensMap(seralizedMap); 0262 0263 // Check the actual mapping result 0264 const QStringList mapping = m_screenMapper->disabledScreensMap(); 0265 qDebug() << "mapping:" << mapping; 0266 0267 QCOMPARE(mapping.count(), expectedMapping.size() * expectedMapping[0].size()); 0268 0269 for (int i = 0; i < mapping.count() - (expectedMapping[0].size() - 1); i += expectedMapping[0].size()) { 0270 const QStringList configGroup{mapping[i], mapping[i + 1], mapping[i + 2], mapping[i + 3], mapping[i + 4]}; 0271 bool matched = false; 0272 for (const QStringList &expectedConfigGroup : expectedMapping) { 0273 if (expectedConfigGroup[0] == mapping[i] && expectedConfigGroup[1] == mapping[i + 1]) { 0274 QVERIFY(expectedConfigGroup[2] == mapping[i + 2]); 0275 for (int j = 3; j < 3 + mapping[i + 2].toInt(); ++j) { 0276 QVERIFY(std::find(expectedConfigGroup.cbegin(), expectedConfigGroup.cend(), mapping[i + j]) != expectedConfigGroup.cend()); 0277 } 0278 matched = true; 0279 break; 0280 } 0281 } 0282 QVERIFY(matched); 0283 } 0284 } 0285 0286 void ScreenMapperTest::addScreens(const QUrl &path, const QString &activity) 0287 { 0288 for (int screen = 0; screen < 3; screen++) { 0289 m_screenMapper->addScreen(screen, activity, path); 0290 } 0291 }