source: mainline/uspace/lib/display/test/display.c@ 973efd36

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 973efd36 was b093a62, checked in by Jiri Svoboda <jiri@…>, 6 years ago

Fix event delivery test

There was an infinite supply of events which prevented proper shutdown

  • Property mode set to 100644
File size: 13.2 KB
Line 
1/*
2 * Copyright (c) 2019 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <async.h>
30#include <errno.h>
31#include <display.h>
32#include <disp_srv.h>
33#include <fibril_synch.h>
34#include <gfx/color.h>
35#include <gfx/context.h>
36#include <gfx/render.h>
37#include <ipcgfx/server.h>
38#include <loc.h>
39#include <pcut/pcut.h>
40
41PCUT_INIT;
42
43PCUT_TEST_SUITE(display);
44
45static const char *test_display_server = "test-display";
46static const char *test_display_svc = "test/display";
47
48static void test_display_conn(ipc_call_t *, void *);
49static void test_kbd_event(void *, kbd_event_t *);
50
51static errno_t test_window_create(void *, sysarg_t *);
52static errno_t test_window_destroy(void *, sysarg_t);
53static errno_t test_get_event(void *, sysarg_t *, display_wnd_ev_t *);
54
55static errno_t test_gc_set_color(void *, gfx_color_t *);
56
57static display_ops_t test_display_srv_ops = {
58 .window_create = test_window_create,
59 .window_destroy = test_window_destroy,
60 .get_event = test_get_event
61};
62
63static display_wnd_cb_t test_display_wnd_cb = {
64 .kbd_event = test_kbd_event
65};
66
67static gfx_context_ops_t test_gc_ops = {
68 .set_color = test_gc_set_color
69};
70
71/** Describes to the server how to respond to our request and pass tracking
72 * data back to the client.
73 */
74typedef struct {
75 errno_t rc;
76 sysarg_t wnd_id;
77 display_wnd_ev_t event;
78 display_wnd_ev_t revent;
79 int event_cnt;
80 bool window_create_called;
81 bool window_destroy_called;
82 bool get_event_called;
83 bool set_color_called;
84 bool kbd_event_called;
85 fibril_condvar_t kbd_event_cv;
86 fibril_mutex_t kbd_event_lock;
87 display_srv_t *srv;
88} test_response_t;
89
90/** display_open(), display_close() work for valid display service */
91PCUT_TEST(open_close)
92{
93 errno_t rc;
94 service_id_t sid;
95 display_t *disp = NULL;
96 test_response_t resp;
97
98 async_set_fallback_port_handler(test_display_conn, &resp);
99
100 // FIXME This causes this test to be non-reentrant!
101 rc = loc_server_register(test_display_server);
102 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
103
104 rc = loc_service_register(test_display_svc, &sid);
105 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
106
107 rc = display_open(test_display_svc, &disp);
108 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
109 PCUT_ASSERT_NOT_NULL(disp);
110
111 display_close(disp);
112 rc = loc_service_unregister(sid);
113 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
114}
115
116/** display_window_create() with server returning error response works */
117PCUT_TEST(window_create_failure)
118{
119 errno_t rc;
120 service_id_t sid;
121 display_t *disp = NULL;
122 display_window_t *wnd;
123 test_response_t resp;
124
125 async_set_fallback_port_handler(test_display_conn, &resp);
126
127 // FIXME This causes this test to be non-reentrant!
128 rc = loc_server_register(test_display_server);
129 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
130
131 rc = loc_service_register(test_display_svc, &sid);
132 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
133
134 rc = display_open(test_display_svc, &disp);
135 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
136 PCUT_ASSERT_NOT_NULL(disp);
137
138 wnd = NULL;
139 resp.rc = ENOMEM;
140 resp.window_create_called = false;
141 rc = display_window_create(disp, &test_display_wnd_cb, NULL, &wnd);
142 PCUT_ASSERT_TRUE(resp.window_create_called);
143 PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
144 PCUT_ASSERT_NULL(wnd);
145
146 display_close(disp);
147 rc = loc_service_unregister(sid);
148 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
149}
150
151/** display_window_create() and display_window_destroy() with success
152 *
153 * with server returning success,
154 */
155PCUT_TEST(window_create_destroy_success)
156{
157 errno_t rc;
158 service_id_t sid;
159 display_t *disp = NULL;
160 display_window_t *wnd;
161 test_response_t resp;
162
163 async_set_fallback_port_handler(test_display_conn, &resp);
164
165 // FIXME This causes this test to be non-reentrant!
166 rc = loc_server_register(test_display_server);
167 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
168
169 rc = loc_service_register(test_display_svc, &sid);
170 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
171
172 rc = display_open(test_display_svc, &disp);
173 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
174 PCUT_ASSERT_NOT_NULL(disp);
175
176 wnd = NULL;
177 resp.rc = EOK;
178 resp.window_create_called = false;
179 rc = display_window_create(disp, &test_display_wnd_cb, NULL, &wnd);
180 PCUT_ASSERT_TRUE(resp.window_create_called);
181 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
182 PCUT_ASSERT_NOT_NULL(wnd);
183
184 resp.window_destroy_called = false;
185 rc = display_window_destroy(wnd);
186 PCUT_ASSERT_TRUE(resp.window_destroy_called);
187 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
188
189 display_close(disp);
190 rc = loc_service_unregister(sid);
191 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
192}
193
194/** display_window_create() with server returning error response works. */
195PCUT_TEST(window_destroy_failure)
196{
197 errno_t rc;
198 service_id_t sid;
199 display_t *disp = NULL;
200 display_window_t *wnd;
201 test_response_t resp;
202
203 async_set_fallback_port_handler(test_display_conn, &resp);
204
205 // FIXME This causes this test to be non-reentrant!
206 rc = loc_server_register(test_display_server);
207 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
208
209 rc = loc_service_register(test_display_svc, &sid);
210 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
211
212 rc = display_open(test_display_svc, &disp);
213 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
214 PCUT_ASSERT_NOT_NULL(disp);
215
216 resp.rc = EOK;
217 resp.window_create_called = false;
218 rc = display_window_create(disp, &test_display_wnd_cb, NULL, &wnd);
219 PCUT_ASSERT_TRUE(resp.window_create_called);
220 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
221 PCUT_ASSERT_NOT_NULL(wnd);
222
223 resp.rc = EIO;
224 resp.window_destroy_called = false;
225 rc = display_window_destroy(wnd);
226 PCUT_ASSERT_TRUE(resp.window_destroy_called);
227 PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
228
229 display_close(disp);
230 rc = loc_service_unregister(sid);
231 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
232}
233
234/** display_window_get_gc with server returning failure */
235PCUT_TEST(window_get_gc_failure)
236{
237 errno_t rc;
238 service_id_t sid;
239 display_t *disp = NULL;
240 display_window_t *wnd;
241 test_response_t resp;
242 gfx_context_t *gc;
243
244 async_set_fallback_port_handler(test_display_conn, &resp);
245
246 // FIXME This causes this test to be non-reentrant!
247 rc = loc_server_register(test_display_server);
248 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
249
250 rc = loc_service_register(test_display_svc, &sid);
251 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
252
253 rc = display_open(test_display_svc, &disp);
254 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
255 PCUT_ASSERT_NOT_NULL(disp);
256
257 wnd = NULL;
258 resp.rc = EOK;
259 rc = display_window_create(disp, &test_display_wnd_cb, NULL, &wnd);
260 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
261 PCUT_ASSERT_NOT_NULL(wnd);
262
263 gc = NULL;
264 resp.rc = ENOMEM;
265 rc = display_window_get_gc(wnd, &gc);
266 /* async_connect_me_to() does not return specific error */
267 PCUT_ASSERT_ERRNO_VAL(EIO, rc);
268 PCUT_ASSERT_NULL(gc);
269
270 resp.rc = EOK;
271 rc = display_window_destroy(wnd);
272 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
273
274 display_close(disp);
275 rc = loc_service_unregister(sid);
276 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
277}
278
279/** display_window_get_gc with server returning success */
280PCUT_TEST(window_get_gc_success)
281{
282 errno_t rc;
283 service_id_t sid;
284 display_t *disp = NULL;
285 display_window_t *wnd;
286 test_response_t resp;
287 gfx_context_t *gc;
288 gfx_color_t *color;
289
290 async_set_fallback_port_handler(test_display_conn, &resp);
291
292 // FIXME This causes this test to be non-reentrant!
293 rc = loc_server_register(test_display_server);
294 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
295
296 rc = loc_service_register(test_display_svc, &sid);
297 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
298
299 rc = display_open(test_display_svc, &disp);
300 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
301 PCUT_ASSERT_NOT_NULL(disp);
302
303 wnd = NULL;
304 resp.rc = EOK;
305 rc = display_window_create(disp, &test_display_wnd_cb, NULL, &wnd);
306 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
307 PCUT_ASSERT_NOT_NULL(wnd);
308
309 gc = NULL;
310 rc = display_window_get_gc(wnd, &gc);
311 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
312 PCUT_ASSERT_NOT_NULL(gc);
313
314 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
315 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
316
317 resp.set_color_called = false;
318 rc = gfx_set_color(gc, color);
319 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
320 PCUT_ASSERT_TRUE(resp.set_color_called);
321
322 gfx_color_delete(color);
323
324 rc = display_window_destroy(wnd);
325 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
326
327 display_close(disp);
328 rc = loc_service_unregister(sid);
329 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
330}
331
332/** Keyboard event can be delivered from server to client callback function */
333PCUT_TEST(kbd_event_deliver)
334{
335 errno_t rc;
336 service_id_t sid;
337 display_t *disp = NULL;
338 display_window_t *wnd;
339 test_response_t resp;
340 gfx_context_t *gc;
341
342 async_set_fallback_port_handler(test_display_conn, &resp);
343
344 // FIXME This causes this test to be non-reentrant!
345 rc = loc_server_register(test_display_server);
346 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
347
348 rc = loc_service_register(test_display_svc, &sid);
349 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
350
351 rc = display_open(test_display_svc, &disp);
352 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
353 PCUT_ASSERT_NOT_NULL(disp);
354 PCUT_ASSERT_NOT_NULL(resp.srv);
355
356 wnd = NULL;
357 resp.rc = EOK;
358 rc = display_window_create(disp, &test_display_wnd_cb, (void *) &resp,
359 &wnd);
360 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
361 PCUT_ASSERT_NOT_NULL(wnd);
362
363 gc = NULL;
364 rc = display_window_get_gc(wnd, &gc);
365 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
366 PCUT_ASSERT_NOT_NULL(gc);
367
368 resp.event_cnt = 1;
369 resp.event.kbd_event.type = KEY_PRESS;
370 resp.event.kbd_event.key = KC_ENTER;
371 resp.event.kbd_event.mods = 0;
372 resp.event.kbd_event.c = L'\0';
373 resp.wnd_id = wnd->id;
374 resp.kbd_event_called = false;
375 fibril_mutex_initialize(&resp.kbd_event_lock);
376 fibril_condvar_initialize(&resp.kbd_event_cv);
377 display_srv_ev_pending(resp.srv);
378
379 /* Wait for the event handler to be called. */
380 fibril_mutex_lock(&resp.kbd_event_lock);
381 while (!resp.kbd_event_called) {
382 fibril_condvar_wait(&resp.kbd_event_cv, &resp.kbd_event_lock);
383 }
384 fibril_mutex_unlock(&resp.kbd_event_lock);
385
386 /* Verify that the event was delivered correctly */
387 PCUT_ASSERT_EQUALS(resp.event.kbd_event.type,
388 resp.revent.kbd_event.type);
389 PCUT_ASSERT_EQUALS(resp.event.kbd_event.key,
390 resp.revent.kbd_event.key);
391 PCUT_ASSERT_EQUALS(resp.event.kbd_event.mods,
392 resp.revent.kbd_event.mods);
393 PCUT_ASSERT_EQUALS(resp.event.kbd_event.c,
394 resp.revent.kbd_event.c);
395
396 rc = display_window_destroy(wnd);
397 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
398
399 display_close(disp);
400
401 rc = loc_service_unregister(sid);
402 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
403}
404
405/** Test display service connection.
406 *
407 * This is very similar to connection handler in the display server.
408 * XXX This should be folded into display_srv, if possible
409 */
410static void test_display_conn(ipc_call_t *icall, void *arg)
411{
412 test_response_t *resp = (test_response_t *) arg;
413 display_srv_t srv;
414 sysarg_t wnd_id;
415 sysarg_t svc_id;
416 gfx_context_t *gc;
417 errno_t rc;
418
419 svc_id = ipc_get_arg2(icall);
420 wnd_id = ipc_get_arg3(icall);
421
422 if (svc_id != 0) {
423 /* Set up protocol structure */
424 display_srv_initialize(&srv);
425 srv.ops = &test_display_srv_ops;
426 srv.arg = arg;
427 resp->srv = &srv;
428
429 /* Handle connection */
430 display_conn(icall, &srv);
431
432 resp->srv = NULL;
433 } else {
434 (void) wnd_id;
435
436 if (resp->rc != EOK) {
437 async_answer_0(icall, resp->rc);
438 return;
439 }
440
441 rc = gfx_context_new(&test_gc_ops, arg, &gc);
442 if (rc != EOK) {
443 async_answer_0(icall, ENOMEM);
444 return;
445 }
446
447 /* Window GC connection */
448 gc_conn(icall, gc);
449 }
450}
451
452static void test_kbd_event(void *arg, kbd_event_t *event)
453{
454 test_response_t *resp = (test_response_t *) arg;
455
456 resp->revent.kbd_event = *event;
457
458 fibril_mutex_lock(&resp->kbd_event_lock);
459 resp->kbd_event_called = true;
460 fibril_condvar_broadcast(&resp->kbd_event_cv);
461 fibril_mutex_unlock(&resp->kbd_event_lock);
462}
463
464static errno_t test_window_create(void *arg, sysarg_t *rwnd_id)
465{
466 test_response_t *resp = (test_response_t *) arg;
467
468 resp->window_create_called = true;
469 if (resp->rc == EOK)
470 *rwnd_id = resp->wnd_id;
471
472 return resp->rc;
473}
474
475static errno_t test_window_destroy(void *arg, sysarg_t wnd_id)
476{
477 test_response_t *resp = (test_response_t *) arg;
478
479 resp->window_destroy_called = true;
480 return resp->rc;
481}
482
483static errno_t test_get_event(void *arg, sysarg_t *wnd_id, display_wnd_ev_t *event)
484{
485 test_response_t *resp = (test_response_t *) arg;
486
487 resp->get_event_called = true;
488 if (resp->event_cnt > 0) {
489 --resp->event_cnt;
490 *wnd_id = resp->wnd_id;
491 *event = resp->event;
492 return EOK;
493 }
494
495 return ENOENT;
496}
497
498static errno_t test_gc_set_color(void *arg, gfx_color_t *color)
499{
500 test_response_t *resp = (test_response_t *) arg;
501
502 resp->set_color_called = true;
503 return resp->rc;
504}
505
506PCUT_EXPORT(display);
Note: See TracBrowser for help on using the repository browser.