File indexing completed on 2025-01-26 05:09:26

0001 /*
0002  * This file is part of the KDE wacomtablet project. For copyright
0003  * information and license terms see the AUTHORS and COPYING files
0004  * in the top-level directory of this distribution.
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU General Public License as
0008  * published by the Free Software Foundation; either version 2 of
0009  * the License, or (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License
0017  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0018  */
0019 
0020 #include "../kdedtestutils.h"
0021 #include "../tabletbackendmock.h"
0022 
0023 #include "common/screensinfo.h"
0024 #include "common/tabletinformation.h"
0025 #include "kded/tabletbackendfactory.h"
0026 #include "kded/tablethandler.h"
0027 
0028 #include <QtTest>
0029 
0030 using namespace Wacom;
0031 
0032 /**
0033  * @file testdbustabletservice.cpp
0034  *
0035  * @test UnitTest for ...
0036  * @todo use QSignalSpy?
0037  */
0038 class TestTabletHandler : public QObject
0039 {
0040     Q_OBJECT
0041 
0042 public Q_SLOTS:
0043     void onNotify(const QString &eventId, const QString &title, const QString &message, bool suggestConfigure);
0044     void onProfileChanged(const QString &tabletID, const QString &profile);
0045     void onTabletAdded(const TabletInformation &info);
0046     void onTabletRemoved(const QString &tabletID);
0047 
0048 private slots:
0049     void initTestCase();
0050     void test();
0051     void cleanupTestCase();
0052 
0053 private:
0054     void testListProfiles();
0055     void testOnScreenRotated();
0056     void testOnTabletAdded();
0057     void testOnTabletRemoved();
0058     void testOnTogglePenMode();
0059     void testOnToggleTouch();
0060     void testSetProfile();
0061     void testSetProperty();
0062 
0063     QString m_notifyEventId;
0064     QString m_notifyTitle;
0065     QString m_notifyMessage;
0066 
0067     QString m_profileChanged;
0068 
0069     TabletInformation m_tabletAddedInformation;
0070     bool m_tabletAdded;
0071     bool m_tabletRemoved;
0072 
0073     TabletHandler *m_tabletHandler;
0074     TabletBackendMock *m_backendMock;
0075 };
0076 
0077 QTEST_MAIN(TestTabletHandler)
0078 
0079 void TestTabletHandler::onNotify(const QString &eventId, const QString &title, const QString &message, bool suggestConfigure)
0080 {
0081     Q_UNUSED(suggestConfigure)
0082 
0083     m_notifyEventId = eventId;
0084     m_notifyTitle = title;
0085     m_notifyMessage = message;
0086 }
0087 
0088 void TestTabletHandler::onProfileChanged(const QString &tabletID, const QString &profile)
0089 {
0090     Q_UNUSED(tabletID)
0091 
0092     m_profileChanged = profile;
0093 }
0094 
0095 void TestTabletHandler::onTabletAdded(const TabletInformation &info)
0096 {
0097     m_tabletRemoved = false;
0098     m_tabletAdded = true;
0099     m_tabletAddedInformation = info;
0100 }
0101 
0102 void TestTabletHandler::onTabletRemoved(const QString &tabletID)
0103 {
0104     Q_UNUSED(tabletID)
0105 
0106     m_tabletAdded = false;
0107     m_tabletRemoved = true;
0108 }
0109 
0110 void TestTabletHandler::initTestCase()
0111 {
0112     m_tabletAdded = false;
0113     m_tabletRemoved = false;
0114     m_backendMock = nullptr;
0115 
0116     TabletBackendFactory::setUnitTest(true);
0117 
0118     QString profilePath = KdedTestUtils::getAbsolutePath(QLatin1String("testtablethandler.profilesrc"));
0119     QString configPath = KdedTestUtils::getAbsolutePath(QLatin1String("testtablethandler.configrc"));
0120     m_tabletHandler = new TabletHandler(profilePath, configPath);
0121 
0122     connect(m_tabletHandler, &TabletHandler::notify, this, &TestTabletHandler::onNotify);
0123     connect(m_tabletHandler, &TabletHandler::profileChanged, this, &TestTabletHandler::onProfileChanged);
0124     connect(m_tabletHandler, &TabletHandler::tabletAdded, this, &TestTabletHandler::onTabletAdded);
0125     connect(m_tabletHandler, &TabletHandler::tabletRemoved, this, &TestTabletHandler::onTabletRemoved);
0126 }
0127 
0128 void TestTabletHandler::cleanupTestCase()
0129 {
0130     delete m_tabletHandler;
0131 }
0132 
0133 void TestTabletHandler::test()
0134 {
0135     // only one test method as the test has to be executed in a specific order
0136     testOnTabletAdded();
0137 
0138     testSetProperty();
0139 
0140     testListProfiles();
0141 
0142     testSetProfile();
0143 
0144     testOnTogglePenMode();
0145 
0146     testOnToggleTouch();
0147 
0148     testOnScreenRotated();
0149 
0150     testOnTabletRemoved();
0151 }
0152 
0153 void TestTabletHandler::testListProfiles()
0154 {
0155     QStringList profiles = m_tabletHandler->listProfiles(QLatin1String("4321"));
0156 
0157     QCOMPARE(profiles.size(), 2);
0158     QVERIFY(profiles.contains(QLatin1String("default")));
0159     QVERIFY(profiles.contains(QLatin1String("test")));
0160 
0161     QWARN("testListProfiles(): PASSED!");
0162 }
0163 
0164 void TestTabletHandler::testOnScreenRotated()
0165 {
0166     m_tabletHandler->onMapToScreen1();
0167     // reset screen rotation
0168     m_tabletHandler->setProperty(QLatin1String("4321"), DeviceType::Stylus, Property::Rotate, ScreenRotation::NONE.key());
0169     m_tabletHandler->setProperty(QLatin1String("4321"), DeviceType::Eraser, Property::Rotate, ScreenRotation::NONE.key());
0170     m_tabletHandler->setProperty(QLatin1String("4321"), DeviceType::Touch, Property::Rotate, ScreenRotation::NONE.key());
0171 
0172     // we need the test profile set as it has the required property
0173     QCOMPARE(m_profileChanged, QLatin1String("test"));
0174 
0175     // compare start parameters
0176     QCOMPARE(m_tabletHandler->getProperty(QLatin1String("4321"), DeviceType::Eraser, Property::Rotate), ScreenRotation::NONE.key());
0177     QCOMPARE(m_tabletHandler->getProperty(QLatin1String("4321"), DeviceType::Stylus, Property::Rotate), ScreenRotation::NONE.key());
0178     QCOMPARE(m_tabletHandler->getProperty(QLatin1String("4321"), DeviceType::Touch, Property::Rotate), ScreenRotation::NONE.key());
0179 
0180     // rotate screen
0181     m_tabletHandler->onScreenRotated(ScreensInfo::getPrimaryScreenName(), Qt::InvertedLandscapeOrientation);
0182 
0183     // validate result
0184     QCOMPARE(m_tabletHandler->getProperty(QLatin1String("4321"), DeviceType::Eraser, Property::Rotate), ScreenRotation::HALF.key());
0185     QCOMPARE(m_tabletHandler->getProperty(QLatin1String("4321"), DeviceType::Stylus, Property::Rotate), ScreenRotation::HALF.key());
0186     QCOMPARE(m_tabletHandler->getProperty(QLatin1String("4321"), DeviceType::Touch, Property::Rotate), ScreenRotation::HALF.key());
0187 
0188     QWARN("testOnScreenRotated(): PASSED!");
0189 }
0190 
0191 void TestTabletHandler::testOnTabletAdded()
0192 {
0193     QVERIFY(!m_tabletAdded);
0194     QVERIFY(!m_tabletRemoved);
0195 
0196     // Do not initialize the factory yet so it can not return a backend.
0197     TabletInformation basicInfo;
0198     m_notifyEventId.clear();
0199     m_notifyMessage.clear();
0200     m_notifyTitle.clear();
0201 
0202     // if the tablet backend factory returns NULL adding a tablet should fail
0203     TabletBackendFactory::setUnitTest(true);
0204     TabletBackendFactory::setTabletBackendMock(NULL);
0205 
0206     m_tabletHandler->onTabletAdded(basicInfo);
0207 
0208     QVERIFY(!m_tabletAdded);
0209     QVERIFY(!m_tabletRemoved);
0210     QVERIFY(m_notifyEventId.isEmpty());
0211     QVERIFY(m_notifyMessage.isEmpty());
0212     QVERIFY(m_notifyTitle.isEmpty());
0213     QVERIFY(m_profileChanged.isEmpty());
0214 
0215     // create a valid backend for the factory to return
0216     m_backendMock = new TabletBackendMock();
0217 
0218     m_backendMock->m_tabletInformation.set(TabletInfo::TabletSerial, QLatin1String("123"));
0219     m_backendMock->m_tabletInformation.set(TabletInfo::CompanyId, QLatin1String("1234"));
0220     m_backendMock->m_tabletInformation.set(TabletInfo::CompanyName, QLatin1String("Company"));
0221     m_backendMock->m_tabletInformation.set(TabletInfo::TabletId, QLatin1String("4321"));
0222     m_backendMock->m_tabletInformation.set(TabletInfo::TabletModel, QLatin1String("Tablet Model"));
0223     m_backendMock->m_tabletInformation.set(TabletInfo::TabletName, QLatin1String("Bamboo Create"));
0224     m_backendMock->m_tabletInformation.set(TabletInfo::NumPadButtons, QLatin1String("4"));
0225     m_backendMock->m_tabletInformation.setAvailable(true);
0226 
0227     DeviceInformation devInfoEraser(DeviceType::Eraser, QLatin1String("Eraser Device"));
0228     DeviceInformation devInfoStylus(DeviceType::Stylus, QLatin1String("Stylus Device"));
0229     DeviceInformation devInfoTouch(DeviceType::Touch, QLatin1String("Touch Device"));
0230 
0231     m_backendMock->m_tabletInformation.setDevice(devInfoEraser);
0232     m_backendMock->m_tabletInformation.setDevice(devInfoStylus);
0233     m_backendMock->m_tabletInformation.setDevice(devInfoTouch);
0234 
0235     TabletBackendFactory::setTabletBackendMock(m_backendMock);
0236 
0237     // add a tablet
0238     m_tabletHandler->onTabletAdded(m_backendMock->getInformation());
0239 
0240     QVERIFY(!m_tabletRemoved);
0241     QVERIFY(m_tabletAdded);
0242     QVERIFY(!m_notifyEventId.isEmpty());
0243     QVERIFY(!m_notifyMessage.isEmpty());
0244     QVERIFY(!m_notifyTitle.isEmpty());
0245     QVERIFY(!m_profileChanged.isEmpty());
0246     QCOMPARE(m_profileChanged, QLatin1String("test"));
0247     QCOMPARE(m_backendMock->m_tabletProfile.getName(), QLatin1String("test"));
0248 
0249     m_tabletAdded = false;
0250     m_notifyEventId.clear();
0251     m_notifyMessage.clear();
0252     m_notifyTitle.clear();
0253     m_profileChanged.clear();
0254 
0255     // add the tablet again
0256     m_tabletHandler->onTabletAdded(m_backendMock->getInformation());
0257 
0258     QVERIFY(!m_tabletRemoved);
0259     QVERIFY(!m_tabletAdded);
0260     QVERIFY(m_notifyEventId.isEmpty());
0261     QVERIFY(m_notifyMessage.isEmpty());
0262     QVERIFY(m_notifyTitle.isEmpty());
0263     QVERIFY(m_profileChanged.isEmpty());
0264 
0265     QWARN("testOnTabletAdded(): PASSED!");
0266 
0267     // prepare for the next test
0268     m_tabletAdded = true;
0269 }
0270 
0271 void TestTabletHandler::testOnTabletRemoved()
0272 {
0273     QVERIFY(!m_tabletRemoved);
0274     QVERIFY(m_tabletAdded);
0275 
0276     m_notifyEventId.clear();
0277     m_notifyMessage.clear();
0278     m_notifyTitle.clear();
0279 
0280     TabletInformation info;
0281 
0282     // removing a different tablet then the one handled by the backend should do nothing
0283     info.set(TabletInfo::TabletSerial, QLatin1String("12"));
0284     m_tabletHandler->onTabletRemoved(info);
0285 
0286     QVERIFY(!m_tabletRemoved);
0287     QVERIFY(m_tabletAdded);
0288     QVERIFY(m_notifyEventId.isEmpty());
0289     QVERIFY(m_notifyMessage.isEmpty());
0290     QVERIFY(m_notifyTitle.isEmpty());
0291 
0292     // remove the currently managed tablet
0293     // this should emit a signal and notify the user
0294     info.set(TabletInfo::TabletSerial, QLatin1String("123"));
0295     info.set(TabletInfo::TabletId, QLatin1String("4321"));
0296     m_tabletHandler->onTabletRemoved(info);
0297 
0298     QVERIFY(m_tabletRemoved);
0299     QVERIFY(!m_tabletAdded);
0300     QVERIFY(!m_notifyEventId.isEmpty());
0301     QVERIFY(!m_notifyMessage.isEmpty());
0302     QVERIFY(!m_notifyTitle.isEmpty());
0303 
0304     m_backendMock = NULL; // no longer valid, as tablet was removed
0305 
0306     // remove the device again.
0307     m_tabletRemoved = false;
0308     m_notifyEventId.clear();
0309     m_notifyMessage.clear();
0310     m_notifyTitle.clear();
0311 
0312     m_tabletHandler->onTabletRemoved(info);
0313 
0314     QVERIFY(!m_tabletRemoved);
0315     QVERIFY(!m_tabletAdded);
0316     QVERIFY(m_notifyEventId.isEmpty());
0317     QVERIFY(m_notifyMessage.isEmpty());
0318     QVERIFY(m_notifyTitle.isEmpty());
0319 
0320     QWARN("testOnTabletRemoved(): PASSED!");
0321 }
0322 
0323 void TestTabletHandler::testOnTogglePenMode()
0324 {
0325     m_backendMock->setProperty(DeviceType::Stylus, Property::Mode, QLatin1String("Absolute"));
0326     m_backendMock->setProperty(DeviceType::Eraser, Property::Mode, QLatin1String("Absolute"));
0327 
0328     QCOMPARE(m_backendMock->getProperty(DeviceType::Eraser, Property::Mode), QLatin1String("Absolute"));
0329     QCOMPARE(m_backendMock->getProperty(DeviceType::Stylus, Property::Mode), QLatin1String("Absolute"));
0330 
0331     m_tabletHandler->onTogglePenMode();
0332 
0333     QCOMPARE(m_backendMock->getProperty(DeviceType::Eraser, Property::Mode), QLatin1String("relative"));
0334     QCOMPARE(m_backendMock->getProperty(DeviceType::Stylus, Property::Mode), QLatin1String("relative"));
0335 
0336     m_tabletHandler->onTogglePenMode();
0337 
0338     QCOMPARE(m_backendMock->getProperty(DeviceType::Eraser, Property::Mode), QLatin1String("absolute"));
0339     QCOMPARE(m_backendMock->getProperty(DeviceType::Stylus, Property::Mode), QLatin1String("absolute"));
0340 
0341     QWARN("testOnTogglePenMode(): PASSED!");
0342 }
0343 
0344 void TestTabletHandler::testOnToggleTouch()
0345 {
0346     m_tabletHandler->setProperty(QLatin1String("4321"), DeviceType::Touch, Property::Touch, QLatin1String("off"));
0347 
0348     QCOMPARE(m_backendMock->getProperty(DeviceType::Touch, Property::Touch), QLatin1String("off"));
0349     QCOMPARE(m_tabletHandler->getProperty(QLatin1String("4321"), DeviceType::Touch, Property::Touch), QLatin1String("off"));
0350 
0351     m_tabletHandler->onToggleTouch();
0352 
0353     QCOMPARE(m_backendMock->getProperty(DeviceType::Touch, Property::Touch), QLatin1String("on"));
0354 
0355     m_tabletHandler->onToggleTouch();
0356 
0357     QCOMPARE(m_backendMock->getProperty(DeviceType::Touch, Property::Touch), QLatin1String("off"));
0358 
0359     QWARN("testOnToggleTouch(): PASSED!");
0360 }
0361 
0362 void TestTabletHandler::testSetProfile()
0363 {
0364     m_profileChanged.clear();
0365     m_notifyEventId.clear();
0366     m_notifyMessage.clear();
0367     m_notifyTitle.clear();
0368 
0369     // set invalid profile first
0370     m_tabletHandler->setProfile(QLatin1String("4321"), QLatin1String("InvalidProfile"));
0371 
0372     QVERIFY(!m_profileChanged.isEmpty());
0373     QCOMPARE(m_profileChanged, m_tabletHandler->listProfiles(QLatin1String("4321")).first());
0374     QVERIFY(!m_notifyEventId.isEmpty());
0375     QVERIFY(!m_notifyMessage.isEmpty());
0376     QVERIFY(!m_notifyTitle.isEmpty());
0377 
0378     // set a valid profile
0379     m_notifyEventId.clear();
0380     m_notifyMessage.clear();
0381     m_notifyTitle.clear();
0382 
0383     m_tabletHandler->setProfile(QLatin1String("4321"), QLatin1String("default"));
0384 
0385     QVERIFY(m_notifyEventId.isEmpty());
0386     QVERIFY(m_notifyMessage.isEmpty());
0387     QVERIFY(m_notifyTitle.isEmpty());
0388     QCOMPARE(m_profileChanged, QLatin1String("default"));
0389     QCOMPARE(m_backendMock->m_tabletProfile.getName(), QLatin1String("default"));
0390 
0391     // set the profile back to "test" so we can run this tests
0392     // multiple times in a row. Otherwise the test will fail as
0393     // cmake copies our test data only once.
0394     m_tabletHandler->setProfile(QLatin1String("4321"), QLatin1String("test"));
0395 
0396     QWARN("testSetProfile(): PASSED!");
0397 }
0398 
0399 void TestTabletHandler::testSetProperty()
0400 {
0401     QVERIFY(m_tabletAdded);
0402 
0403     m_tabletHandler->setProperty(QLatin1String("4321"), DeviceType::Stylus, Property::Button1, Property::Button1.key());
0404     QCOMPARE(m_backendMock->getProperty(DeviceType::Stylus, Property::Button1), Property::Button1.key());
0405     QCOMPARE(m_tabletHandler->getProperty(QLatin1String("4321"), DeviceType::Stylus, Property::Button1), Property::Button1.key());
0406 
0407     QWARN("testSetProperty(): PASSED!");
0408 }
0409 
0410 #include "testtablethandler.moc"