source: mainline/uspace/lib/display/test/display.c@ 4d9c807

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

Communicate window dimensions to display server

  • Property mode set to 100644
File size: 15.1 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 *, display_wnd_params_t *, 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 gfx_rect_t create_rect;
82 bool window_destroy_called;
83 bool get_event_called;
84 bool set_color_called;
85 bool kbd_event_called;
86 fibril_condvar_t kbd_event_cv;
87 fibril_mutex_t kbd_event_lock;
88 display_srv_t *srv;
89} test_response_t;
90
91/** display_open(), display_close() work for valid display service */
92PCUT_TEST(open_close)
93{
94 errno_t rc;
95 service_id_t sid;
96 display_t *disp = NULL;
97 test_response_t resp;
98
99 async_set_fallback_port_handler(test_display_conn, &resp);
100
101 // FIXME This causes this test to be non-reentrant!
102 rc = loc_server_register(test_display_server);
103 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
104
105 rc = loc_service_register(test_display_svc, &sid);
106 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
107
108 rc = display_open(test_display_svc, &disp);
109 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
110 PCUT_ASSERT_NOT_NULL(disp);
111
112 display_close(disp);
113 rc = loc_service_unregister(sid);
114 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
115}
116
117/** display_window_create() with server returning error response works */
118PCUT_TEST(window_create_failure)
119{
120 errno_t rc;
121 service_id_t sid;
122 display_t *disp = NULL;
123 display_wnd_params_t params;
124 display_window_t *wnd;
125 test_response_t resp;
126
127 async_set_fallback_port_handler(test_display_conn, &resp);
128
129 // FIXME This causes this test to be non-reentrant!
130 rc = loc_server_register(test_display_server);
131 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
132
133 rc = loc_service_register(test_display_svc, &sid);
134 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
135
136 rc = display_open(test_display_svc, &disp);
137 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
138 PCUT_ASSERT_NOT_NULL(disp);
139
140 wnd = NULL;
141 resp.rc = ENOMEM;
142 resp.window_create_called = false;
143 display_wnd_params_init(&params);
144 params.rect.p0.x = 0;
145 params.rect.p0.y = 0;
146 params.rect.p0.x = 100;
147 params.rect.p0.y = 100;
148
149 rc = display_window_create(disp, &params, &test_display_wnd_cb,
150 (void *) &resp, &wnd);
151 PCUT_ASSERT_TRUE(resp.window_create_called);
152 PCUT_ASSERT_EQUALS(params.rect.p0.x, resp.create_rect.p0.x);
153 PCUT_ASSERT_EQUALS(params.rect.p0.y, resp.create_rect.p0.y);
154 PCUT_ASSERT_EQUALS(params.rect.p1.x, resp.create_rect.p1.x);
155 PCUT_ASSERT_EQUALS(params.rect.p1.y, resp.create_rect.p1.y);
156 PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
157 PCUT_ASSERT_NULL(wnd);
158
159 display_close(disp);
160 rc = loc_service_unregister(sid);
161 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
162}
163
164/** display_window_create() and display_window_destroy() with success
165 *
166 * with server returning success,
167 */
168PCUT_TEST(window_create_destroy_success)
169{
170 errno_t rc;
171 service_id_t sid;
172 display_t *disp = NULL;
173 display_wnd_params_t params;
174 display_window_t *wnd;
175 test_response_t resp;
176
177 async_set_fallback_port_handler(test_display_conn, &resp);
178
179 // FIXME This causes this test to be non-reentrant!
180 rc = loc_server_register(test_display_server);
181 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
182
183 rc = loc_service_register(test_display_svc, &sid);
184 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
185
186 rc = display_open(test_display_svc, &disp);
187 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
188 PCUT_ASSERT_NOT_NULL(disp);
189
190 wnd = NULL;
191 resp.rc = EOK;
192 resp.window_create_called = false;
193 display_wnd_params_init(&params);
194 params.rect.p0.x = 0;
195 params.rect.p0.y = 0;
196 params.rect.p0.x = 100;
197 params.rect.p0.y = 100;
198
199 rc = display_window_create(disp, &params, &test_display_wnd_cb,
200 (void *) &resp, &wnd);
201 PCUT_ASSERT_TRUE(resp.window_create_called);
202 PCUT_ASSERT_EQUALS(params.rect.p0.x, resp.create_rect.p0.x);
203 PCUT_ASSERT_EQUALS(params.rect.p0.y, resp.create_rect.p0.y);
204 PCUT_ASSERT_EQUALS(params.rect.p1.x, resp.create_rect.p1.x);
205 PCUT_ASSERT_EQUALS(params.rect.p1.y, resp.create_rect.p1.y);
206 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
207 PCUT_ASSERT_NOT_NULL(wnd);
208
209 resp.window_destroy_called = false;
210 rc = display_window_destroy(wnd);
211 PCUT_ASSERT_TRUE(resp.window_destroy_called);
212 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
213
214 display_close(disp);
215 rc = loc_service_unregister(sid);
216 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
217}
218
219/** display_window_create() with server returning error response works. */
220PCUT_TEST(window_destroy_failure)
221{
222 errno_t rc;
223 service_id_t sid;
224 display_t *disp = NULL;
225 display_wnd_params_t params;
226 display_window_t *wnd;
227 test_response_t resp;
228
229 async_set_fallback_port_handler(test_display_conn, &resp);
230
231 // FIXME This causes this test to be non-reentrant!
232 rc = loc_server_register(test_display_server);
233 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
234
235 rc = loc_service_register(test_display_svc, &sid);
236 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
237
238 rc = display_open(test_display_svc, &disp);
239 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
240 PCUT_ASSERT_NOT_NULL(disp);
241
242 resp.rc = EOK;
243 resp.window_create_called = false;
244 display_wnd_params_init(&params);
245 params.rect.p0.x = 0;
246 params.rect.p0.y = 0;
247 params.rect.p0.x = 100;
248 params.rect.p0.y = 100;
249
250 rc = display_window_create(disp, &params, &test_display_wnd_cb,
251 (void *) &resp, &wnd);
252 PCUT_ASSERT_TRUE(resp.window_create_called);
253 PCUT_ASSERT_EQUALS(params.rect.p0.x, resp.create_rect.p0.x);
254 PCUT_ASSERT_EQUALS(params.rect.p0.y, resp.create_rect.p0.y);
255 PCUT_ASSERT_EQUALS(params.rect.p1.x, resp.create_rect.p1.x);
256 PCUT_ASSERT_EQUALS(params.rect.p1.y, resp.create_rect.p1.y);
257 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
258 PCUT_ASSERT_NOT_NULL(wnd);
259
260 resp.rc = EIO;
261 resp.window_destroy_called = false;
262 rc = display_window_destroy(wnd);
263 PCUT_ASSERT_TRUE(resp.window_destroy_called);
264 PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
265
266 display_close(disp);
267 rc = loc_service_unregister(sid);
268 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
269}
270
271/** display_window_get_gc with server returning failure */
272PCUT_TEST(window_get_gc_failure)
273{
274 errno_t rc;
275 service_id_t sid;
276 display_t *disp = NULL;
277 display_wnd_params_t params;
278 display_window_t *wnd;
279 test_response_t resp;
280 gfx_context_t *gc;
281
282 async_set_fallback_port_handler(test_display_conn, &resp);
283
284 // FIXME This causes this test to be non-reentrant!
285 rc = loc_server_register(test_display_server);
286 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
287
288 rc = loc_service_register(test_display_svc, &sid);
289 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
290
291 rc = display_open(test_display_svc, &disp);
292 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
293 PCUT_ASSERT_NOT_NULL(disp);
294
295 wnd = NULL;
296 resp.rc = EOK;
297 display_wnd_params_init(&params);
298 params.rect.p0.x = 0;
299 params.rect.p0.y = 0;
300 params.rect.p0.x = 100;
301 params.rect.p0.y = 100;
302
303 rc = display_window_create(disp, &params, &test_display_wnd_cb,
304 (void *) &resp, &wnd);
305 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
306 PCUT_ASSERT_NOT_NULL(wnd);
307
308 gc = NULL;
309 resp.rc = ENOMEM;
310 rc = display_window_get_gc(wnd, &gc);
311 /* async_connect_me_to() does not return specific error */
312 PCUT_ASSERT_ERRNO_VAL(EIO, rc);
313 PCUT_ASSERT_NULL(gc);
314
315 resp.rc = EOK;
316 rc = display_window_destroy(wnd);
317 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
318
319 display_close(disp);
320 rc = loc_service_unregister(sid);
321 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
322}
323
324/** display_window_get_gc with server returning success */
325PCUT_TEST(window_get_gc_success)
326{
327 errno_t rc;
328 service_id_t sid;
329 display_t *disp = NULL;
330 display_wnd_params_t params;
331 display_window_t *wnd;
332 test_response_t resp;
333 gfx_context_t *gc;
334 gfx_color_t *color;
335
336 async_set_fallback_port_handler(test_display_conn, &resp);
337
338 // FIXME This causes this test to be non-reentrant!
339 rc = loc_server_register(test_display_server);
340 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
341
342 rc = loc_service_register(test_display_svc, &sid);
343 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
344
345 rc = display_open(test_display_svc, &disp);
346 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
347 PCUT_ASSERT_NOT_NULL(disp);
348
349 wnd = NULL;
350 resp.rc = EOK;
351 display_wnd_params_init(&params);
352 params.rect.p0.x = 0;
353 params.rect.p0.y = 0;
354 params.rect.p0.x = 100;
355 params.rect.p0.y = 100;
356
357 rc = display_window_create(disp, &params, &test_display_wnd_cb,
358 (void *) &resp, &wnd);
359 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
360 PCUT_ASSERT_NOT_NULL(wnd);
361
362 gc = NULL;
363 rc = display_window_get_gc(wnd, &gc);
364 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
365 PCUT_ASSERT_NOT_NULL(gc);
366
367 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
368 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
369
370 resp.set_color_called = false;
371 rc = gfx_set_color(gc, color);
372 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
373 PCUT_ASSERT_TRUE(resp.set_color_called);
374
375 gfx_color_delete(color);
376
377 rc = display_window_destroy(wnd);
378 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
379
380 display_close(disp);
381 rc = loc_service_unregister(sid);
382 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
383}
384
385/** Keyboard event can be delivered from server to client callback function */
386PCUT_TEST(kbd_event_deliver)
387{
388 errno_t rc;
389 service_id_t sid;
390 display_t *disp = NULL;
391 display_wnd_params_t params;
392 display_window_t *wnd;
393 test_response_t resp;
394 gfx_context_t *gc;
395
396 async_set_fallback_port_handler(test_display_conn, &resp);
397
398 // FIXME This causes this test to be non-reentrant!
399 rc = loc_server_register(test_display_server);
400 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
401
402 rc = loc_service_register(test_display_svc, &sid);
403 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
404
405 rc = display_open(test_display_svc, &disp);
406 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
407 PCUT_ASSERT_NOT_NULL(disp);
408 PCUT_ASSERT_NOT_NULL(resp.srv);
409
410 wnd = NULL;
411 resp.rc = EOK;
412 display_wnd_params_init(&params);
413 params.rect.p0.x = 0;
414 params.rect.p0.y = 0;
415 params.rect.p0.x = 100;
416 params.rect.p0.y = 100;
417
418 rc = display_window_create(disp, &params, &test_display_wnd_cb,
419 (void *) &resp, &wnd);
420 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
421 PCUT_ASSERT_NOT_NULL(wnd);
422
423 gc = NULL;
424 rc = display_window_get_gc(wnd, &gc);
425 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
426 PCUT_ASSERT_NOT_NULL(gc);
427
428 resp.event_cnt = 1;
429 resp.event.kbd_event.type = KEY_PRESS;
430 resp.event.kbd_event.key = KC_ENTER;
431 resp.event.kbd_event.mods = 0;
432 resp.event.kbd_event.c = L'\0';
433 resp.wnd_id = wnd->id;
434 resp.kbd_event_called = false;
435 fibril_mutex_initialize(&resp.kbd_event_lock);
436 fibril_condvar_initialize(&resp.kbd_event_cv);
437 display_srv_ev_pending(resp.srv);
438
439 /* Wait for the event handler to be called. */
440 fibril_mutex_lock(&resp.kbd_event_lock);
441 while (!resp.kbd_event_called) {
442 fibril_condvar_wait(&resp.kbd_event_cv, &resp.kbd_event_lock);
443 }
444 fibril_mutex_unlock(&resp.kbd_event_lock);
445
446 /* Verify that the event was delivered correctly */
447 PCUT_ASSERT_EQUALS(resp.event.kbd_event.type,
448 resp.revent.kbd_event.type);
449 PCUT_ASSERT_EQUALS(resp.event.kbd_event.key,
450 resp.revent.kbd_event.key);
451 PCUT_ASSERT_EQUALS(resp.event.kbd_event.mods,
452 resp.revent.kbd_event.mods);
453 PCUT_ASSERT_EQUALS(resp.event.kbd_event.c,
454 resp.revent.kbd_event.c);
455
456 rc = display_window_destroy(wnd);
457 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
458
459 display_close(disp);
460
461 rc = loc_service_unregister(sid);
462 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
463}
464
465/** Test display service connection.
466 *
467 * This is very similar to connection handler in the display server.
468 * XXX This should be folded into display_srv, if possible
469 */
470static void test_display_conn(ipc_call_t *icall, void *arg)
471{
472 test_response_t *resp = (test_response_t *) arg;
473 display_srv_t srv;
474 sysarg_t wnd_id;
475 sysarg_t svc_id;
476 gfx_context_t *gc;
477 errno_t rc;
478
479 svc_id = ipc_get_arg2(icall);
480 wnd_id = ipc_get_arg3(icall);
481
482 if (svc_id != 0) {
483 /* Set up protocol structure */
484 display_srv_initialize(&srv);
485 srv.ops = &test_display_srv_ops;
486 srv.arg = arg;
487 resp->srv = &srv;
488
489 /* Handle connection */
490 display_conn(icall, &srv);
491
492 resp->srv = NULL;
493 } else {
494 (void) wnd_id;
495
496 if (resp->rc != EOK) {
497 async_answer_0(icall, resp->rc);
498 return;
499 }
500
501 rc = gfx_context_new(&test_gc_ops, arg, &gc);
502 if (rc != EOK) {
503 async_answer_0(icall, ENOMEM);
504 return;
505 }
506
507 /* Window GC connection */
508 gc_conn(icall, gc);
509 }
510}
511
512static void test_kbd_event(void *arg, kbd_event_t *event)
513{
514 test_response_t *resp = (test_response_t *) arg;
515
516 resp->revent.kbd_event = *event;
517
518 fibril_mutex_lock(&resp->kbd_event_lock);
519 resp->kbd_event_called = true;
520 fibril_condvar_broadcast(&resp->kbd_event_cv);
521 fibril_mutex_unlock(&resp->kbd_event_lock);
522}
523
524static errno_t test_window_create(void *arg, display_wnd_params_t *params,
525 sysarg_t *rwnd_id)
526{
527 test_response_t *resp = (test_response_t *) arg;
528
529 resp->window_create_called = true;
530 resp->create_rect = params->rect;
531 if (resp->rc == EOK)
532 *rwnd_id = resp->wnd_id;
533
534 return resp->rc;
535}
536
537static errno_t test_window_destroy(void *arg, sysarg_t wnd_id)
538{
539 test_response_t *resp = (test_response_t *) arg;
540
541 resp->window_destroy_called = true;
542 return resp->rc;
543}
544
545static errno_t test_get_event(void *arg, sysarg_t *wnd_id, display_wnd_ev_t *event)
546{
547 test_response_t *resp = (test_response_t *) arg;
548
549 resp->get_event_called = true;
550 if (resp->event_cnt > 0) {
551 --resp->event_cnt;
552 *wnd_id = resp->wnd_id;
553 *event = resp->event;
554 return EOK;
555 }
556
557 return ENOENT;
558}
559
560static errno_t test_gc_set_color(void *arg, gfx_color_t *color)
561{
562 test_response_t *resp = (test_response_t *) arg;
563
564 resp->set_color_called = true;
565 return resp->rc;
566}
567
568PCUT_EXPORT(display);
Note: See TracBrowser for help on using the repository browser.