/* SPDX-FileCopyrightText: 2017 Klarälvdalens Datakonsult AB a KDAB Group company Work sponsored by the LiMux project of the city of Munich. SPDX-FileContributor: Andras Mantia SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "screenmappertest.h" #include "screenmapper.h" #include #include #include QTEST_MAIN(ScreenMapperTest) void ScreenMapperTest::initTestCase() { m_screenMapper = ScreenMapper::instance(); m_currentActivity = KActivities::Consumer().currentActivity(); m_alternativeActivity = QStringLiteral("a779f58a-b5e3-426d-9994-a8c54d26d528"); // Generated by uuidgen Q_ASSERT(m_currentActivity != m_alternativeActivity); } void ScreenMapperTest::init() { m_screenMapper->cleanup(); } void ScreenMapperTest::tst_addScreens() { const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); QSignalSpy s(m_screenMapper, &ScreenMapper::screensChanged); m_screenMapper->addScreen(-1, m_currentActivity, path); QCOMPARE(s.count(), 0); m_screenMapper->addScreen(1, m_currentActivity, path); QCOMPARE(s.count(), 1); m_screenMapper->addScreen(0, m_currentActivity, path); QCOMPARE(s.count(), 2); m_screenMapper->addScreen(1, m_currentActivity, path); QCOMPARE(s.count(), 2); // Test if activity ID works m_screenMapper->addScreen(1, m_alternativeActivity, path); QCOMPARE(s.count(), 3); m_screenMapper->addScreen(3, m_alternativeActivity, path); QCOMPARE(s.count(), 4); QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 0); QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_alternativeActivity), 1); } void ScreenMapperTest::tst_removeScreens() { const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); addScreens(path, m_currentActivity); addScreens(path, m_alternativeActivity); QSignalSpy s(m_screenMapper, &ScreenMapper::screensChanged); m_screenMapper->removeScreen(-1, m_currentActivity, path); QCOMPARE(s.count(), 0); m_screenMapper->removeScreen(1, m_currentActivity, path); QCOMPARE(s.count(), 1); QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 0); m_screenMapper->removeScreen(1, m_currentActivity, path); QCOMPARE(s.count(), 1); m_screenMapper->addScreen(3, m_currentActivity, path); QCOMPARE(s.count(), 2); m_screenMapper->removeScreen(0, m_currentActivity, path); QCOMPARE(s.count(), 3); QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 2); // Remove screens on m_currentActivity should not affect screens on m_alternativeActivity QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_alternativeActivity), 0); m_screenMapper->removeScreen(2, m_alternativeActivity, path); QCOMPARE(s.count(), 4); // Remove screens on m_alternativeActivity should not affect screens on m_currentActivity QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 2); } void ScreenMapperTest::tst_addMapping() { const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); addScreens(path, m_currentActivity); addScreens(path, m_alternativeActivity); QSignalSpy s(m_screenMapper, &ScreenMapper::screenMappingChanged); QString file(QStringLiteral("desktop:/foo%1.txt")); for (int i = 0; i < 3; i++) { const QUrl url = ScreenMapper::stringToUrl(file.arg(i)); m_screenMapper->addMapping(url, i, m_currentActivity); QCOMPARE(s.count(), i + 1); QCOMPARE(m_screenMapper->screenForItem(url, m_currentActivity), i); // Mappings added to m_currentActivity should not affect mappings on m_alternativeActivity QCOMPARE(m_screenMapper->screenForItem(url, m_alternativeActivity), -1); } } void ScreenMapperTest::tst_addRemoveScreenWithItems() { const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); addScreens(path, m_currentActivity); addScreens(path, m_alternativeActivity); QString file(QStringLiteral("desktop:/foo%1.txt")); for (int i = 0; i < 3; i++) { const QUrl url = ScreenMapper::stringToUrl(file.arg(i)); for (const QString &activity : {m_currentActivity, m_alternativeActivity}) { m_screenMapper->addMapping(url, i, activity); } } // remove one screen m_screenMapper->removeScreen(1, m_currentActivity, path); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(0)), m_currentActivity), 0); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_currentActivity), -1); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(2)), m_currentActivity), 2); // Remove a screen of m_currentActivity should not affect screens of m_alternativeActivity QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_alternativeActivity), 1); // add removed screen back, items screen is restored m_screenMapper->addScreen(1, m_currentActivity, path); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(0)), m_currentActivity), 0); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_currentActivity), 1); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(2)), m_currentActivity), 2); // Restore a screen of m_currentActivity should not affect screens of m_alternativeActivity QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_alternativeActivity), 1); // remove all screens, firstAvailableScreen changes m_screenMapper->removeScreen(0, m_currentActivity, path); QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 1); m_screenMapper->removeScreen(1, m_currentActivity, path); QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 2); m_screenMapper->removeScreen(2, m_currentActivity, path); QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), -1); // Remove screens of m_currentActivity should not affect screens of m_alternativeActivity QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_alternativeActivity), 0); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(0)), m_currentActivity), -1); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_currentActivity), -1); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(2)), m_currentActivity), -1); // add all screens back, all item's screen is restored addScreens(path, m_currentActivity); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(0)), m_currentActivity), 0); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(1)), m_currentActivity), 1); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(file.arg(2)), m_currentActivity), 2); // remove one screen and move its item const QUrl movedItem = ScreenMapper::stringToUrl(file.arg(1)); m_screenMapper->removeScreen(1, m_currentActivity, path); QCOMPARE(m_screenMapper->screenForItem(movedItem, m_currentActivity), -1); m_screenMapper->addMapping(movedItem, 0, m_currentActivity); QCOMPARE(m_screenMapper->screenForItem(movedItem, m_currentActivity), 0); QCOMPARE(m_screenMapper->screenForItem(movedItem, m_alternativeActivity), 1); // add back the screen, item goes back to the original place m_screenMapper->addScreen(1, m_currentActivity, path); QCOMPARE(m_screenMapper->screenForItem(movedItem, m_currentActivity), 1); QCOMPARE(m_screenMapper->screenForItem(movedItem, m_alternativeActivity), 1); } void ScreenMapperTest::tst_addRemoveScreenDifferentPaths() { const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/Foo")); const auto path2 = ScreenMapper::stringToUrl(QStringLiteral("desktop:/Foo2")); m_screenMapper->addScreen(0, m_currentActivity, path); QCOMPARE(m_screenMapper->firstAvailableScreen(path, m_currentActivity), 0); QCOMPARE(m_screenMapper->firstAvailableScreen(path2, m_currentActivity), -1); } void ScreenMapperTest::tst_readScreenActivityMapping() { const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); addScreens(path, m_currentActivity); addScreens(path, m_alternativeActivity); QString file(QStringLiteral("desktop:/foo%1.txt")); const QStringList paths{ file.arg(0), file.arg(1), }; // clang-format off const QStringList mapping{ paths[0], "0", m_currentActivity, paths[1], "1", m_currentActivity, paths[0], "1", m_alternativeActivity, }; // clang-format on QSignalSpy s(m_screenMapper, &ScreenMapper::screenMappingChanged); m_screenMapper->setScreenMapping(mapping); QCOMPARE(s.count(), 1); // Check if the config is loaded correctly QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[0]), m_currentActivity), 0); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[1]), m_currentActivity), 1); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[0]), m_alternativeActivity), 1); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[1]), m_alternativeActivity), -1); } void ScreenMapperTest::tst_readScreenActivityMappingFromOldConfig() { const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); addScreens(path, m_currentActivity); QString file(QStringLiteral("desktop:/foo%1.txt")); const QStringList paths{ file.arg(0), file.arg(1), }; // clang-format off const QStringList mapping{ paths[0], "0", paths[1], "1", }; // clang-format on QSignalSpy s(m_screenMapper, &ScreenMapper::screenMappingChanged); m_screenMapper->setScreenMapping(mapping); QCOMPARE(s.count(), 1); // Check if the config is loaded correctly QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[0]), m_currentActivity), 0); QCOMPARE(m_screenMapper->screenForItem(ScreenMapper::stringToUrl(paths[1]), m_currentActivity), 1); } void ScreenMapperTest::tst_saveScreenActivityMapping() { const auto path = ScreenMapper::stringToUrl(QStringLiteral("desktop:/")); addScreens(path, m_currentActivity); addScreens(path, m_alternativeActivity); QString file(QStringLiteral("desktop:/foo%1.txt")); const std::array expectedMapping{ QStringList{file.arg(0), "0", m_currentActivity}, QStringList{file.arg(1), "1", m_currentActivity}, QStringList{file.arg(0), "1", m_alternativeActivity}, }; for (const auto &l : expectedMapping) { m_screenMapper->addMapping(ScreenMapper::stringToUrl(l[0]), l[1].toInt(), l[2]); } const QStringList mapping = m_screenMapper->screenMapping(); QCOMPARE(mapping.count(), expectedMapping.size() * expectedMapping[0].size()); for (int i = 0; i < mapping.count() - (expectedMapping[0].size() - 1); i += expectedMapping[0].size()) { const QStringList configGroup{mapping[i], mapping[i + 1], mapping[i + 2]}; QVERIFY(std::find(std::cbegin(expectedMapping), std::cend(expectedMapping), configGroup) != std::cend(expectedMapping)); } } void ScreenMapperTest::tst_readAndSaveItemsOnActivitiesOnDisabledScreens() { QString file(QStringLiteral("desktop:/foo%1.txt")); const QStringList paths{ ScreenMapper::stringToUrl(file.arg(0)).toString(), ScreenMapper::stringToUrl(file.arg(1)).toString(), ScreenMapper::stringToUrl(file.arg(2)).toString(), ScreenMapper::stringToUrl(file.arg(3)).toString(), }; // clang-format off const std::array expectedMapping{ QStringList{"0", m_currentActivity, "2", paths[0], paths[1]}, QStringList{"1", m_currentActivity, "2", paths[2], paths[3]}, QStringList{"0", m_alternativeActivity, "2", paths[0], paths[1]}, }; // clang-format on QStringList seralizedMap; // Create a seralized QStringList from expectedMapping for (const auto &l : expectedMapping) { for (const auto &s : l) { seralizedMap.append(s); } } m_screenMapper->readDisabledScreensMap(seralizedMap); // Check the actual mapping result const QStringList mapping = m_screenMapper->disabledScreensMap(); QCOMPARE(mapping.count(), expectedMapping.size() * expectedMapping[0].size()); for (int i = 0; i < mapping.count() - (expectedMapping[0].size() - 1); i += expectedMapping[0].size()) { const QStringList configGroup{mapping[i], mapping[i + 1], mapping[i + 2], mapping[i + 3], mapping[i + 4]}; QVERIFY(std::find(std::cbegin(expectedMapping), std::cend(expectedMapping), configGroup) != std::cend(expectedMapping)); } } void ScreenMapperTest::tst_readAndSaveItemsOnActivitiesOnDisabledScreensFromOldConfig() { QString file(QStringLiteral("desktop:/foo%1.txt")); const QStringList paths{ ScreenMapper::stringToUrl(file.arg(0)).toString(), ScreenMapper::stringToUrl(file.arg(1)).toString(), ScreenMapper::stringToUrl(file.arg(2)).toString(), ScreenMapper::stringToUrl(file.arg(3)).toString(), }; // clang-format off const std::array expectedMapping{ QStringList{"0", m_currentActivity, "2", paths[0], paths[1]}, QStringList{"1", m_currentActivity, "2", paths[2], paths[3]}, }; // clang-format on QStringList seralizedMap; // Create a seralized QStringList from expectedMapping for (const auto &l : expectedMapping) { for (const auto &s : l) { if (s == m_currentActivity) { continue; // Missing activity ID from the old config before 5.25 } seralizedMap.append(s); } } m_screenMapper->readDisabledScreensMap(seralizedMap); // Check the actual mapping result const QStringList mapping = m_screenMapper->disabledScreensMap(); QCOMPARE(mapping.count(), expectedMapping.size() * expectedMapping[0].size()); for (int i = 0; i < mapping.count() - (expectedMapping[0].size() - 1); i += expectedMapping[0].size()) { const QStringList configGroup{mapping[i], mapping[i + 1], mapping[i + 2], mapping[i + 3], mapping[i + 4]}; QVERIFY(std::find(std::cbegin(expectedMapping), std::cend(expectedMapping), configGroup) != std::cend(expectedMapping)); } } void ScreenMapperTest::addScreens(const QUrl &path, const QString &activity) { for (int screen = 0; screen < 3; screen++) { m_screenMapper->addScreen(screen, activity, path); } }