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(&registry, &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"