Changeset View
Changeset View
Standalone View
Standalone View
autotests/client/test_remote_access.cpp
- This file was added.
1 | /******************************************************************** | ||||
---|---|---|---|---|---|
2 | Copyright 2016 Oleg Chernovskiy <kanedias@xaker.ru> | ||||
3 | | ||||
4 | This library is free software; you can redistribute it and/or | ||||
5 | modify it under the terms of the GNU Lesser General Public | ||||
6 | License as published by the Free Software Foundation; either | ||||
7 | version 2.1 of the License, or (at your option) version 3, or any | ||||
8 | later version accepted by the membership of KDE e.V. (or its | ||||
9 | successor approved by the membership of KDE e.V.), which shall | ||||
10 | act as a proxy defined in Section 6 of version 3 of the license. | ||||
11 | | ||||
12 | This library is distributed in the hope that it will be useful, | ||||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
15 | Lesser General Public License for more details. | ||||
16 | | ||||
17 | You should have received a copy of the GNU Lesser General Public | ||||
18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | *********************************************************************/ | ||||
20 | // Qt | ||||
21 | #include <QtTest/QtTest> | ||||
22 | // client | ||||
23 | #include "../../src/client/connection_thread.h" | ||||
24 | #include "../../src/client/event_queue.h" | ||||
25 | #include "../../src/client/remote_access.h" | ||||
26 | #include "../../src/client/registry.h" | ||||
27 | // server | ||||
28 | #include "../../src/server/display.h" | ||||
29 | #include "../../src/server/remote_access_interface.h" | ||||
30 | | ||||
31 | #include <linux/input.h> | ||||
32 | | ||||
33 | using namespace KWayland::Client; | ||||
34 | using namespace KWayland::Server; | ||||
35 | | ||||
36 | Q_DECLARE_METATYPE(const BufferHandle *) | ||||
37 | | ||||
38 | class RemoteAccessTest : public QObject | ||||
39 | { | ||||
40 | Q_OBJECT | ||||
41 | private Q_SLOTS: | ||||
42 | void init(); | ||||
43 | void cleanup(); | ||||
44 | | ||||
45 | void testSendReleaseSingle(); | ||||
46 | void testSendReleaseMultiple(); | ||||
47 | void testSendClientGone(); | ||||
48 | void testSendReceiveClientGone(); | ||||
49 | | ||||
50 | private: | ||||
51 | Display *m_display = nullptr; | ||||
52 | RemoteAccessManagerInterface *m_remoteAccessInterface = nullptr; | ||||
53 | ConnectionThread *m_connection = nullptr; | ||||
54 | QThread *m_thread = nullptr; | ||||
55 | EventQueue *m_queue = nullptr; | ||||
56 | Registry *m_registry = nullptr; | ||||
57 | }; | ||||
58 | | ||||
59 | static const QString s_socketName = QStringLiteral("kwayland-test-remote-access-0"); | ||||
60 | | ||||
61 | void RemoteAccessTest::init() | ||||
62 | { | ||||
63 | qRegisterMetaType<const BufferHandle *>("BufferHandle"); | ||||
64 | | ||||
65 | delete m_display; | ||||
66 | m_display = new Display(this); | ||||
67 | m_display->setSocketName(s_socketName); | ||||
68 | m_display->start(); | ||||
69 | QVERIFY(m_display->isRunning()); | ||||
70 | m_display->createShm(); | ||||
71 | m_remoteAccessInterface = m_display->createRemoteAccessManager(); | ||||
72 | m_remoteAccessInterface->create(); | ||||
73 | QSignalSpy bufferReleasedSpy(m_remoteAccessInterface, &RemoteAccessManagerInterface::bufferReleased); | ||||
74 | QVERIFY(bufferReleasedSpy.isValid()); | ||||
75 | | ||||
76 | // setup connection | ||||
77 | m_connection = new KWayland::Client::ConnectionThread; | ||||
78 | QSignalSpy connectedSpy(m_connection, &ConnectionThread::connected); | ||||
79 | QVERIFY(connectedSpy.isValid()); | ||||
80 | m_connection->setSocketName(s_socketName); | ||||
81 | | ||||
82 | m_thread = new QThread(this); | ||||
83 | m_connection->moveToThread(m_thread); | ||||
84 | m_thread->start(); | ||||
85 | | ||||
86 | m_connection->initConnection(); | ||||
87 | QVERIFY(connectedSpy.wait()); | ||||
88 | | ||||
89 | m_queue = new EventQueue(this); | ||||
90 | m_queue->setup(m_connection); | ||||
91 | | ||||
92 | m_registry = new Registry(this); | ||||
93 | QSignalSpy interfacesAnnouncedSpy(m_registry, &Registry::interfacesAnnounced); | ||||
94 | QVERIFY(interfacesAnnouncedSpy.isValid()); | ||||
95 | m_registry->setEventQueue(m_queue); | ||||
96 | m_registry->create(m_connection); | ||||
97 | QVERIFY(m_registry->isValid()); | ||||
98 | m_registry->setup(); | ||||
99 | QVERIFY(interfacesAnnouncedSpy.wait()); | ||||
100 | } | ||||
101 | | ||||
102 | void RemoteAccessTest::cleanup() | ||||
103 | { | ||||
104 | #define CLEANUP(variable) \ | ||||
105 | if (variable) { \ | ||||
106 | delete variable; \ | ||||
107 | variable = nullptr; \ | ||||
108 | } | ||||
109 | CLEANUP(m_queue) | ||||
110 | CLEANUP(m_registry) | ||||
111 | if (m_thread) { | ||||
112 | if (m_connection) { | ||||
113 | m_connection->flush(); | ||||
114 | m_connection->deleteLater(); | ||||
115 | m_connection = nullptr; | ||||
116 | } | ||||
117 | | ||||
118 | m_thread->quit(); | ||||
119 | m_thread->wait(); | ||||
120 | delete m_thread; | ||||
121 | m_thread = nullptr; | ||||
122 | } | ||||
123 | | ||||
124 | CLEANUP(m_remoteAccessInterface) | ||||
125 | CLEANUP(m_display) | ||||
126 | #undef CLEANUP | ||||
127 | } | ||||
128 | | ||||
129 | void RemoteAccessTest::testSendReleaseSingle() | ||||
130 | { | ||||
131 | // this test verifies that a buffer is sent to client and returned back | ||||
132 | | ||||
133 | // setup | ||||
134 | QVERIFY(!m_remoteAccessInterface->isBound()); | ||||
135 | auto client = m_registry->createRemoteAccessManager( | ||||
136 | m_registry->interface(Registry::Interface::RemoteAccessManager).name, | ||||
137 | m_registry->interface(Registry::Interface::RemoteAccessManager).version, | ||||
138 | this); | ||||
139 | QVERIFY(client->isValid()); | ||||
140 | m_connection->flush(); | ||||
141 | m_display->dispatchEvents(); | ||||
142 | | ||||
143 | QVERIFY(m_remoteAccessInterface->isBound()); // we have one client now | ||||
144 | QSignalSpy bufferReadySpy(client, &RemoteAccessManager::bufferReady); | ||||
145 | QVERIFY(bufferReadySpy.isValid()); | ||||
146 | | ||||
147 | BufferHandle *buf = new BufferHandle(); | ||||
148 | QTemporaryFile *tmpFile = new QTemporaryFile(this); | ||||
149 | tmpFile->open(); | ||||
150 | | ||||
151 | buf->setFd(tmpFile->handle()); | ||||
152 | buf->setSize(50, 50); | ||||
153 | buf->setFormat(100500); | ||||
154 | buf->setStride(7800); | ||||
155 | m_remoteAccessInterface->sendBufferReady(buf); | ||||
156 | | ||||
157 | // receive buffer | ||||
158 | QVERIFY(bufferReadySpy.wait()); | ||||
159 | auto rbuf = bufferReadySpy.takeFirst().first().value<RemoteBuffer *>(); | ||||
160 | QSignalSpy paramsObtainedSpy(rbuf, &RemoteBuffer::parametersObtained); | ||||
161 | QVERIFY(paramsObtainedSpy.isValid()); | ||||
162 | | ||||
163 | // wait for params | ||||
164 | QVERIFY(paramsObtainedSpy.wait()); | ||||
165 | // client fd is different, not subject to check | ||||
166 | QCOMPARE(rbuf->width(), 50u); | ||||
167 | QCOMPARE(rbuf->height(), 50u); | ||||
168 | QCOMPARE(rbuf->format(), 100500u); | ||||
169 | QCOMPARE(rbuf->stride(), 7800u); | ||||
170 | | ||||
171 | // release | ||||
172 | QSignalSpy bufferReleasedSpy(m_remoteAccessInterface, &RemoteAccessManagerInterface::bufferReleased); | ||||
173 | QVERIFY(bufferReleasedSpy.isValid()); | ||||
174 | rbuf->release(); | ||||
175 | QVERIFY(bufferReleasedSpy.wait()); | ||||
176 | | ||||
177 | // cleanup | ||||
178 | delete buf; | ||||
179 | delete client; | ||||
180 | m_connection->flush(); | ||||
181 | m_display->dispatchEvents(); | ||||
182 | QVERIFY(!m_remoteAccessInterface->isBound()); | ||||
183 | } | ||||
184 | | ||||
185 | void RemoteAccessTest::testSendReleaseMultiple() | ||||
186 | { | ||||
187 | // this test verifies that a buffer is sent to 2 clients and returned back | ||||
188 | | ||||
189 | // setup | ||||
190 | QVERIFY(!m_remoteAccessInterface->isBound()); | ||||
191 | auto client1 = m_registry->createRemoteAccessManager( | ||||
192 | m_registry->interface(Registry::Interface::RemoteAccessManager).name, | ||||
193 | m_registry->interface(Registry::Interface::RemoteAccessManager).version, | ||||
194 | this); | ||||
195 | QVERIFY(client1->isValid()); | ||||
196 | auto client2 = m_registry->createRemoteAccessManager( | ||||
197 | m_registry->interface(Registry::Interface::RemoteAccessManager).name, | ||||
198 | m_registry->interface(Registry::Interface::RemoteAccessManager).version, | ||||
199 | this); | ||||
200 | QVERIFY(client2->isValid()); | ||||
201 | m_connection->flush(); | ||||
202 | m_display->dispatchEvents(); | ||||
203 | | ||||
204 | QVERIFY(m_remoteAccessInterface->isBound()); // now we have 2 clients | ||||
205 | QSignalSpy bufferReadySpy1(client1, &RemoteAccessManager::bufferReady); | ||||
206 | QVERIFY(bufferReadySpy1.isValid()); | ||||
207 | QSignalSpy bufferReadySpy2(client2, &RemoteAccessManager::bufferReady); | ||||
208 | QVERIFY(bufferReadySpy2.isValid()); | ||||
209 | | ||||
210 | BufferHandle *buf = new BufferHandle(); | ||||
211 | QTemporaryFile *tmpFile = new QTemporaryFile(this); | ||||
212 | tmpFile->open(); | ||||
213 | | ||||
214 | buf->setFd(tmpFile->handle()); | ||||
215 | buf->setSize(50, 50); | ||||
216 | buf->setFormat(100500); | ||||
217 | buf->setStride(7800); | ||||
218 | m_remoteAccessInterface->sendBufferReady(buf); | ||||
219 | | ||||
220 | // wait for event loop | ||||
221 | QVERIFY(bufferReadySpy1.wait()); | ||||
222 | | ||||
223 | // receive buffer at client 1 | ||||
224 | QCOMPARE(bufferReadySpy1.size(), 1); | ||||
225 | auto rbuf1 = bufferReadySpy1.takeFirst().first().value<RemoteBuffer *>(); | ||||
226 | QSignalSpy paramsObtainedSpy1(rbuf1, &RemoteBuffer::parametersObtained); | ||||
227 | QVERIFY(paramsObtainedSpy1.isValid()); | ||||
228 | | ||||
229 | // receive buffer at client 2 | ||||
230 | QCOMPARE(bufferReadySpy2.size(), 1); | ||||
231 | auto rbuf2 = bufferReadySpy2.takeFirst().first().value<RemoteBuffer *>(); | ||||
232 | QSignalSpy paramsObtainedSpy2(rbuf2, &RemoteBuffer::parametersObtained); | ||||
233 | QVERIFY(paramsObtainedSpy2.isValid()); | ||||
234 | | ||||
235 | // wait for event loop | ||||
236 | QVERIFY(paramsObtainedSpy1.wait()); | ||||
237 | QCOMPARE(paramsObtainedSpy1.size(), 1); | ||||
238 | QCOMPARE(paramsObtainedSpy2.size(), 1); | ||||
239 | | ||||
240 | // release | ||||
241 | QSignalSpy bufferReleasedSpy(m_remoteAccessInterface, &RemoteAccessManagerInterface::bufferReleased); | ||||
242 | QVERIFY(bufferReleasedSpy.isValid()); | ||||
243 | rbuf1->release(); | ||||
244 | QVERIFY(!bufferReleasedSpy.wait(1000)); // one client released, second still holds buffer! | ||||
245 | | ||||
246 | rbuf2->release(); | ||||
247 | QVERIFY(bufferReleasedSpy.wait()); // all clients released, buffer should be freed | ||||
248 | | ||||
249 | // cleanup | ||||
250 | delete buf; | ||||
251 | delete client1; | ||||
252 | delete client2; | ||||
253 | m_connection->flush(); | ||||
254 | m_display->dispatchEvents(); | ||||
255 | QVERIFY(!m_remoteAccessInterface->isBound()); | ||||
256 | } | ||||
257 | | ||||
258 | void RemoteAccessTest::testSendClientGone() | ||||
259 | { | ||||
260 | // this test verifies that when buffer is sent and client is gone, server will release buffer correctly | ||||
261 | QVERIFY(!m_remoteAccessInterface->isBound()); | ||||
262 | auto client = m_registry->createRemoteAccessManager( | ||||
263 | m_registry->interface(Registry::Interface::RemoteAccessManager).name, | ||||
264 | m_registry->interface(Registry::Interface::RemoteAccessManager).version, | ||||
265 | this); | ||||
266 | QVERIFY(client->isValid()); | ||||
267 | m_connection->flush(); | ||||
268 | m_display->dispatchEvents(); | ||||
269 | | ||||
270 | QVERIFY(m_remoteAccessInterface->isBound()); // we have one client now | ||||
271 | QSignalSpy bufferReadySpy(client, &RemoteAccessManager::bufferReady); | ||||
272 | QVERIFY(bufferReadySpy.isValid()); | ||||
273 | | ||||
274 | BufferHandle *buf = new BufferHandle(); | ||||
275 | QTemporaryFile *tmpFile = new QTemporaryFile(this); | ||||
276 | tmpFile->open(); | ||||
277 | | ||||
278 | buf->setFd(tmpFile->handle()); | ||||
279 | buf->setSize(50, 50); | ||||
280 | buf->setFormat(100500); | ||||
281 | buf->setStride(7800); | ||||
282 | m_remoteAccessInterface->sendBufferReady(buf); | ||||
283 | | ||||
284 | // release forcefully | ||||
285 | QSignalSpy bufferReleasedSpy(m_remoteAccessInterface, &RemoteAccessManagerInterface::bufferReleased); | ||||
286 | QVERIFY(bufferReleasedSpy.isValid()); | ||||
287 | delete client; | ||||
288 | QVERIFY(bufferReleasedSpy.wait()); | ||||
289 | | ||||
290 | // cleanup | ||||
291 | delete buf; | ||||
292 | m_connection->flush(); | ||||
293 | m_display->dispatchEvents(); | ||||
294 | QVERIFY(!m_remoteAccessInterface->isBound()); | ||||
295 | } | ||||
296 | | ||||
297 | void RemoteAccessTest::testSendReceiveClientGone() | ||||
298 | { | ||||
299 | // this test verifies that when buffer is sent, received and client is gone, | ||||
300 | // both client and server will release buffer correctly | ||||
301 | QVERIFY(!m_remoteAccessInterface->isBound()); | ||||
302 | auto client = m_registry->createRemoteAccessManager( | ||||
303 | m_registry->interface(Registry::Interface::RemoteAccessManager).name, | ||||
304 | m_registry->interface(Registry::Interface::RemoteAccessManager).version, | ||||
305 | this); | ||||
306 | QVERIFY(client->isValid()); | ||||
307 | m_connection->flush(); | ||||
308 | m_display->dispatchEvents(); | ||||
309 | | ||||
310 | QVERIFY(m_remoteAccessInterface->isBound()); // we have one client now | ||||
311 | QSignalSpy bufferReadySpy(client, &RemoteAccessManager::bufferReady); | ||||
312 | QVERIFY(bufferReadySpy.isValid()); | ||||
313 | | ||||
314 | BufferHandle *buf = new BufferHandle(); | ||||
315 | QTemporaryFile *tmpFile = new QTemporaryFile(this); | ||||
316 | tmpFile->open(); | ||||
317 | | ||||
318 | buf->setFd(tmpFile->handle()); | ||||
319 | buf->setSize(50, 50); | ||||
320 | buf->setFormat(100500); | ||||
321 | buf->setStride(7800); | ||||
322 | m_remoteAccessInterface->sendBufferReady(buf); | ||||
323 | | ||||
324 | // receive buffer | ||||
325 | QVERIFY(bufferReadySpy.wait()); | ||||
326 | auto rbuf = bufferReadySpy.takeFirst().first().value<RemoteBuffer *>(); | ||||
327 | QSignalSpy paramsObtainedSpy(rbuf, &RemoteBuffer::parametersObtained); | ||||
328 | QVERIFY(paramsObtainedSpy.isValid()); | ||||
329 | | ||||
330 | // wait for params | ||||
331 | QVERIFY(paramsObtainedSpy.wait()); | ||||
332 | // client fd is different, not subject to check | ||||
333 | QCOMPARE(rbuf->width(), 50u); | ||||
334 | QCOMPARE(rbuf->height(), 50u); | ||||
335 | QCOMPARE(rbuf->format(), 100500u); | ||||
336 | QCOMPARE(rbuf->stride(), 7800u); | ||||
337 | | ||||
338 | // release forcefully | ||||
339 | QSignalSpy bufferReleasedSpy(m_remoteAccessInterface, &RemoteAccessManagerInterface::bufferReleased); | ||||
340 | QVERIFY(bufferReleasedSpy.isValid()); | ||||
341 | delete client; | ||||
342 | QVERIFY(bufferReleasedSpy.wait()); | ||||
343 | | ||||
344 | // cleanup | ||||
345 | delete buf; | ||||
346 | m_connection->flush(); | ||||
347 | m_display->dispatchEvents(); | ||||
348 | QVERIFY(!m_remoteAccessInterface->isBound()); | ||||
349 | } | ||||
350 | | ||||
351 | | ||||
352 | QTEST_GUILESS_MAIN(RemoteAccessTest) | ||||
353 | #include "test_remote_access.moc" |