KWin
Loading...
Searching...
No Matches
test_datasource.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6// Qt
7#include <QMimeDatabase>
8#include <QSignalSpy>
9#include <QTemporaryFile>
10#include <QTest>
11
13#include "wayland/datasource.h"
14#include "wayland/display.h"
15
16// KWayland
17#include "KWayland/Client/connection_thread.h"
18#include "KWayland/Client/datadevicemanager.h"
19#include "KWayland/Client/datasource.h"
20#include "KWayland/Client/event_queue.h"
21#include "KWayland/Client/registry.h"
22
23// Wayland
24#include <wayland-client.h>
25
26class TestDataSource : public QObject
27{
28 Q_OBJECT
29private Q_SLOTS:
30 void init();
31 void cleanup();
32
33 void testOffer();
34 void testTargetAccepts_data();
35 void testTargetAccepts();
36 void testRequestSend();
37 void testCancel();
38 void testServerGet();
39
40private:
41 KWin::Display *m_display = nullptr;
42 KWin::DataDeviceManagerInterface *m_dataDeviceManagerInterface = nullptr;
43 KWayland::Client::ConnectionThread *m_connection = nullptr;
44 KWayland::Client::DataDeviceManager *m_dataDeviceManager = nullptr;
45 KWayland::Client::EventQueue *m_queue = nullptr;
46 QThread *m_thread = nullptr;
47};
48
49static const QString s_socketName = QStringLiteral("kwayland-test-wayland-datasource-0");
50
51void TestDataSource::init()
52{
53 using namespace KWin;
54 delete m_display;
55 m_display = new KWin::Display(this);
56 m_display->addSocketName(s_socketName);
57 m_display->start();
58 QVERIFY(m_display->isRunning());
59
60 // setup connection
61 m_connection = new KWayland::Client::ConnectionThread;
62 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
63 m_connection->setSocketName(s_socketName);
64
65 m_thread = new QThread(this);
66 m_connection->moveToThread(m_thread);
67 m_thread->start();
68
69 m_connection->initConnection();
70 QVERIFY(connectedSpy.wait());
71
72 m_queue = new KWayland::Client::EventQueue(this);
73 QVERIFY(!m_queue->isValid());
74 m_queue->setup(m_connection);
75 QVERIFY(m_queue->isValid());
76
77 KWayland::Client::Registry registry;
78 QSignalSpy dataDeviceManagerSpy(&registry, &KWayland::Client::Registry::dataDeviceManagerAnnounced);
79 QVERIFY(!registry.eventQueue());
80 registry.setEventQueue(m_queue);
81 QCOMPARE(registry.eventQueue(), m_queue);
82 registry.create(m_connection->display());
83 QVERIFY(registry.isValid());
84 registry.setup();
85
86 m_dataDeviceManagerInterface = new DataDeviceManagerInterface(m_display, m_display);
87
88 QVERIFY(dataDeviceManagerSpy.wait());
89 m_dataDeviceManager =
90 registry.createDataDeviceManager(dataDeviceManagerSpy.first().first().value<quint32>(), dataDeviceManagerSpy.first().last().value<quint32>(), this);
91}
92
93void TestDataSource::cleanup()
94{
95 if (m_dataDeviceManager) {
96 delete m_dataDeviceManager;
97 m_dataDeviceManager = nullptr;
98 }
99 if (m_queue) {
100 delete m_queue;
101 m_queue = nullptr;
102 }
103 if (m_thread) {
104 m_thread->quit();
105 m_thread->wait();
106 delete m_thread;
107 m_thread = nullptr;
108 }
109 delete m_connection;
110 m_connection = nullptr;
111
112 delete m_display;
113 m_display = nullptr;
114}
115
116void TestDataSource::testOffer()
117{
118 using namespace KWin;
119
120 qRegisterMetaType<KWin::DataSourceInterface *>();
121 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated);
122
123 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource());
124 QVERIFY(dataSource->isValid());
125
126 QVERIFY(dataSourceCreatedSpy.wait());
127 QCOMPARE(dataSourceCreatedSpy.count(), 1);
128
129 QPointer<DataSourceInterface> serverDataSource = dataSourceCreatedSpy.first().first().value<DataSourceInterface *>();
130 QVERIFY(!serverDataSource.isNull());
131 QCOMPARE(serverDataSource->mimeTypes().count(), 0);
132
133 QSignalSpy offeredSpy(serverDataSource.data(), &KWin::AbstractDataSource::mimeTypeOffered);
134
135 const QString plain = QStringLiteral("text/plain");
136 QMimeDatabase db;
137 dataSource->offer(db.mimeTypeForName(plain));
138
139 QVERIFY(offeredSpy.wait());
140 QCOMPARE(offeredSpy.count(), 1);
141 QCOMPARE(offeredSpy.last().first().toString(), plain);
142 QCOMPARE(serverDataSource->mimeTypes().count(), 1);
143 QCOMPARE(serverDataSource->mimeTypes().first(), plain);
144
145 const QString html = QStringLiteral("text/html");
146 dataSource->offer(db.mimeTypeForName(html));
147
148 QVERIFY(offeredSpy.wait());
149 QCOMPARE(offeredSpy.count(), 2);
150 QCOMPARE(offeredSpy.first().first().toString(), plain);
151 QCOMPARE(offeredSpy.last().first().toString(), html);
152 QCOMPARE(serverDataSource->mimeTypes().count(), 2);
153 QCOMPARE(serverDataSource->mimeTypes().first(), plain);
154 QCOMPARE(serverDataSource->mimeTypes().last(), html);
155
156 // try destroying the client side, should trigger a destroy of server side
157 dataSource.reset();
158 QVERIFY(!serverDataSource.isNull());
159 wl_display_flush(m_connection->display());
160 QCoreApplication::processEvents();
161 QVERIFY(serverDataSource.isNull());
162}
163
164void TestDataSource::testTargetAccepts_data()
165{
166 QTest::addColumn<QString>("mimeType");
167
168 QTest::newRow("empty") << QString();
169 QTest::newRow("text/plain") << QStringLiteral("text/plain");
170}
171
172void TestDataSource::testTargetAccepts()
173{
174 using namespace KWin;
175
176 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated);
177
178 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource());
179 QVERIFY(dataSource->isValid());
180
181 QSignalSpy targetAcceptsSpy(dataSource.get(), &KWayland::Client::DataSource::targetAccepts);
182
183 QVERIFY(dataSourceCreatedSpy.wait());
184 QCOMPARE(dataSourceCreatedSpy.count(), 1);
185
186 QFETCH(QString, mimeType);
187 dataSourceCreatedSpy.first().first().value<DataSourceInterface *>()->accept(mimeType);
188
189 QVERIFY(targetAcceptsSpy.wait());
190 QCOMPARE(targetAcceptsSpy.count(), 1);
191 QCOMPARE(targetAcceptsSpy.first().first().toString(), mimeType);
192}
193
194void TestDataSource::testRequestSend()
195{
196 using namespace KWin;
197
198 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated);
199
200 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource());
201 QVERIFY(dataSource->isValid());
202 QSignalSpy sendRequestedSpy(dataSource.get(), &KWayland::Client::DataSource::sendDataRequested);
203
204 const QString plain = QStringLiteral("text/plain");
205 QVERIFY(dataSourceCreatedSpy.wait());
206 QCOMPARE(dataSourceCreatedSpy.count(), 1);
207 QTemporaryFile file;
208 QVERIFY(file.open());
209 dataSourceCreatedSpy.first().first().value<DataSourceInterface *>()->requestData(plain, file.handle());
210
211 QVERIFY(sendRequestedSpy.wait());
212 QCOMPARE(sendRequestedSpy.count(), 1);
213 QCOMPARE(sendRequestedSpy.first().first().toString(), plain);
214 QCOMPARE(sendRequestedSpy.first().last().value<qint32>(), file.handle());
215 QVERIFY(sendRequestedSpy.first().last().value<qint32>() != -1);
216
217 QFile writeFile;
218 QVERIFY(writeFile.open(sendRequestedSpy.first().last().value<qint32>(), QFile::WriteOnly, QFileDevice::AutoCloseHandle));
219 writeFile.close();
220}
221
222void TestDataSource::testCancel()
223{
224 using namespace KWin;
225
226 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated);
227
228 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource());
229 QVERIFY(dataSource->isValid());
230 QSignalSpy cancelledSpy(dataSource.get(), &KWayland::Client::DataSource::cancelled);
231
232 QVERIFY(dataSourceCreatedSpy.wait());
233
234 QCOMPARE(cancelledSpy.count(), 0);
235 dataSourceCreatedSpy.first().first().value<DataSourceInterface *>()->cancel();
236
237 QVERIFY(cancelledSpy.wait());
238 QCOMPARE(cancelledSpy.count(), 1);
239}
240
241void TestDataSource::testServerGet()
242{
243 using namespace KWin;
244
245 QSignalSpy dataSourceCreatedSpy(m_dataDeviceManagerInterface, &KWin::DataDeviceManagerInterface::dataSourceCreated);
246
247 std::unique_ptr<KWayland::Client::DataSource> dataSource(m_dataDeviceManager->createDataSource());
248 QVERIFY(dataSource->isValid());
249
250 QVERIFY(!DataSourceInterface::get(nullptr));
251 QVERIFY(dataSourceCreatedSpy.wait());
252 auto d = dataSourceCreatedSpy.first().first().value<DataSourceInterface *>();
253
254 QCOMPARE(DataSourceInterface::get(d->resource()), d);
255 QVERIFY(!DataSourceInterface::get(nullptr));
256}
257
258QTEST_GUILESS_MAIN(TestDataSource)
259#include "test_datasource.moc"
void mimeTypeOffered(const QString &)
virtual void accept(const QString &mimeType)
Represents the Global for wl_data_device_manager interface.
void dataSourceCreated(KWin::DataSourceInterface *)
Represents the Resource for the wl_data_source interface.
Definition datasource.h:23
Class holding the Wayland server display loop.
Definition display.h:34
bool addSocketName(const QString &name=QString())
Definition display.cpp:68
bool isRunning() const
Definition display.cpp:144
bool start()
Definition display.cpp:92
void requestData(const QString &mimeType, qint32 fd) override