File indexing completed on 2024-11-10 04:56:15
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 // Qt 0007 #include <QMimeDatabase> 0008 #include <QSignalSpy> 0009 #include <QTemporaryFile> 0010 #include <QTest> 0011 0012 #include "wayland/datadevicemanager.h" 0013 #include "wayland/datasource.h" 0014 #include "wayland/display.h" 0015 0016 // KWayland 0017 #include "KWayland/Client/connection_thread.h" 0018 #include "KWayland/Client/datadevicemanager.h" 0019 #include "KWayland/Client/datasource.h" 0020 #include "KWayland/Client/event_queue.h" 0021 #include "KWayland/Client/registry.h" 0022 0023 // Wayland 0024 #include <wayland-client.h> 0025 0026 class TestDataSource : public QObject 0027 { 0028 Q_OBJECT 0029 private Q_SLOTS: 0030 void init(); 0031 void cleanup(); 0032 0033 void testOffer(); 0034 void testTargetAccepts_data(); 0035 void testTargetAccepts(); 0036 void testRequestSend(); 0037 void testCancel(); 0038 void testServerGet(); 0039 0040 private: 0041 KWin::Display *m_display = nullptr; 0042 KWin::DataDeviceManagerInterface *m_dataDeviceManagerInterface = nullptr; 0043 KWayland::Client::ConnectionThread *m_connection = nullptr; 0044 KWayland::Client::DataDeviceManager *m_dataDeviceManager = nullptr; 0045 KWayland::Client::EventQueue *m_queue = nullptr; 0046 QThread *m_thread = nullptr; 0047 }; 0048 0049 static const QString s_socketName = QStringLiteral("kwayland-test-wayland-datasource-0"); 0050 0051 void TestDataSource::init() 0052 { 0053 using namespace KWin; 0054 delete m_display; 0055 m_display = new KWin::Display(this); 0056 m_display->addSocketName(s_socketName); 0057 m_display->start(); 0058 QVERIFY(m_display->isRunning()); 0059 0060 // setup connection 0061 m_connection = new KWayland::Client::ConnectionThread; 0062 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected); 0063 m_connection->setSocketName(s_socketName); 0064 0065 m_thread = new QThread(this); 0066 m_connection->moveToThread(m_thread); 0067 m_thread->start(); 0068 0069 m_connection->initConnection(); 0070 QVERIFY(connectedSpy.wait()); 0071 0072 m_queue = new KWayland::Client::EventQueue(this); 0073 QVERIFY(!m_queue->isValid()); 0074 m_queue->setup(m_connection); 0075 QVERIFY(m_queue->isValid()); 0076 0077 KWayland::Client::Registry registry; 0078 QSignalSpy dataDeviceManagerSpy(®istry, &KWayland::Client::Registry::dataDeviceManagerAnnounced); 0079 QVERIFY(!registry.eventQueue()); 0080 registry.setEventQueue(m_queue); 0081 QCOMPARE(registry.eventQueue(), m_queue); 0082 registry.create(m_connection->display()); 0083 QVERIFY(registry.isValid()); 0084 registry.setup(); 0085 0086 m_dataDeviceManagerInterface = new DataDeviceManagerInterface(m_display, m_display); 0087 0088 QVERIFY(dataDeviceManagerSpy.wait()); 0089 m_dataDeviceManager = 0090 registry.createDataDeviceManager(dataDeviceManagerSpy.first().first().value<quint32>(), dataDeviceManagerSpy.first().last().value<quint32>(), this); 0091 } 0092 0093 void TestDataSource::cleanup() 0094 { 0095 if (m_dataDeviceManager) { 0096 delete m_dataDeviceManager; 0097 m_dataDeviceManager = nullptr; 0098 } 0099 if (m_queue) { 0100 delete m_queue; 0101 m_queue = nullptr; 0102 } 0103 if (m_thread) { 0104 m_thread->quit(); 0105 m_thread->wait(); 0106 delete m_thread; 0107 m_thread = nullptr; 0108 } 0109 delete m_connection; 0110 m_connection = nullptr; 0111 0112 delete m_display; 0113 m_display = nullptr; 0114 } 0115 0116 void TestDataSource::testOffer() 0117 { 0118 using namespace KWin; 0119 0120 qRegisterMetaType<KWin::DataSourceInterface *>(); 0121 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated); 0122 0123 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource()); 0124 QVERIFY(dataSource->isValid()); 0125 0126 QVERIFY(dataSourceCreatedSpy.wait()); 0127 QCOMPARE(dataSourceCreatedSpy.count(), 1); 0128 0129 QPointer<DataSourceInterface> serverDataSource = dataSourceCreatedSpy.first().first().value<DataSourceInterface *>(); 0130 QVERIFY(!serverDataSource.isNull()); 0131 QCOMPARE(serverDataSource->mimeTypes().count(), 0); 0132 0133 QSignalSpy offeredSpy(serverDataSource.data(), &KWin::AbstractDataSource::mimeTypeOffered); 0134 0135 const QString plain = QStringLiteral("text/plain"); 0136 QMimeDatabase db; 0137 dataSource->offer(db.mimeTypeForName(plain)); 0138 0139 QVERIFY(offeredSpy.wait()); 0140 QCOMPARE(offeredSpy.count(), 1); 0141 QCOMPARE(offeredSpy.last().first().toString(), plain); 0142 QCOMPARE(serverDataSource->mimeTypes().count(), 1); 0143 QCOMPARE(serverDataSource->mimeTypes().first(), plain); 0144 0145 const QString html = QStringLiteral("text/html"); 0146 dataSource->offer(db.mimeTypeForName(html)); 0147 0148 QVERIFY(offeredSpy.wait()); 0149 QCOMPARE(offeredSpy.count(), 2); 0150 QCOMPARE(offeredSpy.first().first().toString(), plain); 0151 QCOMPARE(offeredSpy.last().first().toString(), html); 0152 QCOMPARE(serverDataSource->mimeTypes().count(), 2); 0153 QCOMPARE(serverDataSource->mimeTypes().first(), plain); 0154 QCOMPARE(serverDataSource->mimeTypes().last(), html); 0155 0156 // try destroying the client side, should trigger a destroy of server side 0157 dataSource.reset(); 0158 QVERIFY(!serverDataSource.isNull()); 0159 wl_display_flush(m_connection->display()); 0160 QCoreApplication::processEvents(); 0161 QVERIFY(serverDataSource.isNull()); 0162 } 0163 0164 void TestDataSource::testTargetAccepts_data() 0165 { 0166 QTest::addColumn<QString>("mimeType"); 0167 0168 QTest::newRow("empty") << QString(); 0169 QTest::newRow("text/plain") << QStringLiteral("text/plain"); 0170 } 0171 0172 void TestDataSource::testTargetAccepts() 0173 { 0174 using namespace KWin; 0175 0176 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated); 0177 0178 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource()); 0179 QVERIFY(dataSource->isValid()); 0180 0181 QSignalSpy targetAcceptsSpy(dataSource.get(), &KWayland::Client::DataSource::targetAccepts); 0182 0183 QVERIFY(dataSourceCreatedSpy.wait()); 0184 QCOMPARE(dataSourceCreatedSpy.count(), 1); 0185 0186 QFETCH(QString, mimeType); 0187 dataSourceCreatedSpy.first().first().value<DataSourceInterface *>()->accept(mimeType); 0188 0189 QVERIFY(targetAcceptsSpy.wait()); 0190 QCOMPARE(targetAcceptsSpy.count(), 1); 0191 QCOMPARE(targetAcceptsSpy.first().first().toString(), mimeType); 0192 } 0193 0194 void TestDataSource::testRequestSend() 0195 { 0196 using namespace KWin; 0197 0198 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated); 0199 0200 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource()); 0201 QVERIFY(dataSource->isValid()); 0202 QSignalSpy sendRequestedSpy(dataSource.get(), &KWayland::Client::DataSource::sendDataRequested); 0203 0204 const QString plain = QStringLiteral("text/plain"); 0205 QVERIFY(dataSourceCreatedSpy.wait()); 0206 QCOMPARE(dataSourceCreatedSpy.count(), 1); 0207 QTemporaryFile file; 0208 QVERIFY(file.open()); 0209 dataSourceCreatedSpy.first().first().value<DataSourceInterface *>()->requestData(plain, file.handle()); 0210 0211 QVERIFY(sendRequestedSpy.wait()); 0212 QCOMPARE(sendRequestedSpy.count(), 1); 0213 QCOMPARE(sendRequestedSpy.first().first().toString(), plain); 0214 QCOMPARE(sendRequestedSpy.first().last().value<qint32>(), file.handle()); 0215 QVERIFY(sendRequestedSpy.first().last().value<qint32>() != -1); 0216 0217 QFile writeFile; 0218 QVERIFY(writeFile.open(sendRequestedSpy.first().last().value<qint32>(), QFile::WriteOnly, QFileDevice::AutoCloseHandle)); 0219 writeFile.close(); 0220 } 0221 0222 void TestDataSource::testCancel() 0223 { 0224 using namespace KWin; 0225 0226 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated); 0227 0228 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource()); 0229 QVERIFY(dataSource->isValid()); 0230 QSignalSpy cancelledSpy(dataSource.get(), &KWayland::Client::DataSource::cancelled); 0231 0232 QVERIFY(dataSourceCreatedSpy.wait()); 0233 0234 QCOMPARE(cancelledSpy.count(), 0); 0235 dataSourceCreatedSpy.first().first().value<DataSourceInterface *>()->cancel(); 0236 0237 QVERIFY(cancelledSpy.wait()); 0238 QCOMPARE(cancelledSpy.count(), 1); 0239 } 0240 0241 void TestDataSource::testServerGet() 0242 { 0243 using namespace KWin; 0244 0245 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated); 0246 0247 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource()); 0248 QVERIFY(dataSource->isValid()); 0249 0250 QVERIFY(!DataSourceInterface::get(nullptr)); 0251 QVERIFY(dataSourceCreatedSpy.wait()); 0252 auto d = dataSourceCreatedSpy.first().first().value<DataSourceInterface *>(); 0253 0254 QCOMPARE(DataSourceInterface::get(d->resource()), d); 0255 QVERIFY(!DataSourceInterface::get(nullptr)); 0256 } 0257 0258 QTEST_GUILESS_MAIN(TestDataSource) 0259 #include "test_datasource.moc"