source: mainline/uspace/lib/ui/test/menu.c@ d65accb

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d65accb was 95a9cbc, checked in by jxsvoboda <5887334+jxsvoboda@…>, 4 years ago

UI menu unit tests

  • Property mode set to 100644
File size: 10.4 KB
RevLine 
[95a9cbc]1/*
2 * Copyright (c) 2021 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 <gfx/context.h>
30#include <gfx/coord.h>
31#include <mem.h>
32#include <pcut/pcut.h>
33#include <stdbool.h>
34#include <str.h>
35#include <ui/control.h>
36#include <ui/menu.h>
37#include <ui/menubar.h>
38#include <ui/resource.h>
39#include <ui/ui.h>
40#include "../private/dummygc.h"
41#include "../private/menu.h"
42#include "../private/menubar.h"
43
44PCUT_INIT;
45
46PCUT_TEST_SUITE(menu);
47
48typedef struct {
49 bool expose;
50} test_resp_t;
51
52static void test_expose(void *);
53
54/** Create and destroy menu */
55PCUT_TEST(create_destroy)
56{
57 ui_menu_bar_t *mbar = NULL;
58 ui_menu_t *menu = NULL;
59 errno_t rc;
60
61 rc = ui_menu_bar_create(NULL, &mbar);
62 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
63
64 rc = ui_menu_create(mbar, "Test", &menu);
65 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
66 PCUT_ASSERT_NOT_NULL(menu);
67
68 /*
69 * Normally we don't need to destroy a menu explicitly, it will
70 * be destroyed along with menu bar, but here we'll test destroying
71 * it explicitly.
72 */
73 ui_menu_destroy(menu);
74 ui_menu_bar_destroy(mbar);
75}
76
77/** ui_menu_destroy() can take NULL argument (no-op) */
78PCUT_TEST(destroy_null)
79{
80 ui_menu_destroy(NULL);
81}
82
83/** ui_menu_first() / ui_menu_next() iterate over menus */
84PCUT_TEST(first_next)
85{
86 dummy_gc_t *dgc;
87 gfx_context_t *gc;
88 ui_resource_t *resource = NULL;
89 ui_menu_bar_t *mbar = NULL;
90 ui_menu_t *menu1 = NULL;
91 ui_menu_t *menu2 = NULL;
92 ui_menu_t *m;
93 errno_t rc;
94
95 rc = dummygc_create(&dgc);
96 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
97
98 gc = dummygc_get_ctx(dgc);
99
100 rc = ui_resource_create(gc, false, &resource);
101 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
102 PCUT_ASSERT_NOT_NULL(resource);
103
104 rc = ui_menu_bar_create(resource, &mbar);
105 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
106 PCUT_ASSERT_NOT_NULL(mbar);
107
108 rc = ui_menu_create(mbar, "Test 1", &menu1);
109 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
110 PCUT_ASSERT_NOT_NULL(menu1);
111
112 rc = ui_menu_create(mbar, "Test 1", &menu2);
113 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
114 PCUT_ASSERT_NOT_NULL(menu2);
115
116 m = ui_menu_first(mbar);
117 PCUT_ASSERT_EQUALS(menu1, m);
118
119 m = ui_menu_next(m);
120 PCUT_ASSERT_EQUALS(menu2, m);
121
122 m = ui_menu_next(m);
123 PCUT_ASSERT_NULL(m);
124
125 ui_menu_bar_destroy(mbar);
126 ui_resource_destroy(resource);
127 dummygc_destroy(dgc);
128}
129
130/** ui_menu_caption() returns the menu's caption */
131PCUT_TEST(caption)
132{
133 dummy_gc_t *dgc;
134 gfx_context_t *gc;
135 ui_resource_t *resource = NULL;
136 ui_menu_bar_t *mbar = NULL;
137 ui_menu_t *menu = NULL;
138 const char *caption;
139 errno_t rc;
140
141 rc = dummygc_create(&dgc);
142 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
143
144 gc = dummygc_get_ctx(dgc);
145
146 rc = ui_resource_create(gc, false, &resource);
147 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
148 PCUT_ASSERT_NOT_NULL(resource);
149
150 rc = ui_menu_bar_create(resource, &mbar);
151 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
152 PCUT_ASSERT_NOT_NULL(mbar);
153
154 rc = ui_menu_create(mbar, "Test", &menu);
155 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
156 PCUT_ASSERT_NOT_NULL(menu);
157
158 caption = ui_menu_caption(menu);
159 PCUT_ASSERT_NOT_NULL(caption);
160
161 PCUT_ASSERT_INT_EQUALS(0, str_cmp(caption, "Test"));
162
163 ui_menu_bar_destroy(mbar);
164 ui_resource_destroy(resource);
165 dummygc_destroy(dgc);
166}
167
168/** ui_menu_get_rect() returns outer menu rectangle */
169PCUT_TEST(get_rect)
170{
171 dummy_gc_t *dgc;
172 gfx_context_t *gc;
173 ui_resource_t *resource = NULL;
174 ui_menu_bar_t *mbar = NULL;
175 ui_menu_t *menu = NULL;
176 gfx_coord2_t pos;
177 gfx_rect_t rect;
178 const char *caption;
179 errno_t rc;
180
181 rc = dummygc_create(&dgc);
182 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
183
184 gc = dummygc_get_ctx(dgc);
185
186 rc = ui_resource_create(gc, false, &resource);
187 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
188 PCUT_ASSERT_NOT_NULL(resource);
189
190 rc = ui_menu_bar_create(resource, &mbar);
191 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
192 PCUT_ASSERT_NOT_NULL(mbar);
193
194 rc = ui_menu_create(mbar, "Test", &menu);
195 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
196 PCUT_ASSERT_NOT_NULL(menu);
197
198 caption = ui_menu_caption(menu);
199 PCUT_ASSERT_NOT_NULL(caption);
200
201 pos.x = 0;
202 pos.y = 0;
203 ui_menu_get_rect(menu, &pos, &rect);
204
205 PCUT_ASSERT_INT_EQUALS(0, rect.p0.x);
206 PCUT_ASSERT_INT_EQUALS(0, rect.p0.y);
207 PCUT_ASSERT_INT_EQUALS(8, rect.p1.x);
208 PCUT_ASSERT_INT_EQUALS(8, rect.p1.y);
209
210 ui_menu_bar_destroy(mbar);
211 ui_resource_destroy(resource);
212 dummygc_destroy(dgc);
213}
214
215/** Paint menu */
216PCUT_TEST(paint)
217{
218 dummy_gc_t *dgc;
219 gfx_context_t *gc;
220 ui_resource_t *resource = NULL;
221 ui_menu_bar_t *mbar = NULL;
222 ui_menu_t *menu = NULL;
223 gfx_coord2_t pos;
224 errno_t rc;
225
226 rc = dummygc_create(&dgc);
227 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
228
229 gc = dummygc_get_ctx(dgc);
230
231 rc = ui_resource_create(gc, false, &resource);
232 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
233 PCUT_ASSERT_NOT_NULL(resource);
234
235 rc = ui_menu_bar_create(resource, &mbar);
236 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
237 PCUT_ASSERT_NOT_NULL(mbar);
238
239 rc = ui_menu_create(mbar, "Test", &menu);
240 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
241 PCUT_ASSERT_NOT_NULL(menu);
242
243 pos.x = 0;
244 pos.y = 0;
245 rc = ui_menu_paint(menu, &pos);
246 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
247
248 ui_menu_bar_destroy(mbar);
249 ui_resource_destroy(resource);
250 dummygc_destroy(dgc);
251}
252
253/** ui_menu_unpaint() calls expose callback */
254PCUT_TEST(unpaint)
255{
256 dummy_gc_t *dgc;
257 gfx_context_t *gc;
258 ui_resource_t *resource = NULL;
259 ui_menu_bar_t *mbar = NULL;
260 ui_menu_t *menu = NULL;
261 test_resp_t resp;
262 errno_t rc;
263
264 rc = dummygc_create(&dgc);
265 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
266
267 gc = dummygc_get_ctx(dgc);
268
269 rc = ui_resource_create(gc, false, &resource);
270 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
271 PCUT_ASSERT_NOT_NULL(resource);
272
273 rc = ui_menu_bar_create(resource, &mbar);
274 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
275 PCUT_ASSERT_NOT_NULL(mbar);
276
277 rc = ui_menu_create(mbar, "Test", &menu);
278 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
279 PCUT_ASSERT_NOT_NULL(menu);
280
281 ui_resource_set_expose_cb(resource, test_expose, &resp);
282
283 resp.expose = false;
284 rc = ui_menu_unpaint(menu);
285 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
286 PCUT_ASSERT_TRUE(resp.expose);
287
288 ui_menu_bar_destroy(mbar);
289 ui_resource_destroy(resource);
290 dummygc_destroy(dgc);
291}
292
293/** ui_menu_pos_event() inside menu is claimed */
294PCUT_TEST(pos_event_inside)
295{
296 dummy_gc_t *dgc;
297 gfx_context_t *gc;
298 ui_resource_t *resource = NULL;
299 ui_menu_bar_t *mbar = NULL;
300 ui_menu_t *menu = NULL;
301 ui_evclaim_t claimed;
302 gfx_coord2_t pos;
303 pos_event_t event;
304 errno_t rc;
305
306 rc = dummygc_create(&dgc);
307 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
308
309 gc = dummygc_get_ctx(dgc);
310
311 rc = ui_resource_create(gc, false, &resource);
312 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
313 PCUT_ASSERT_NOT_NULL(resource);
314
315 rc = ui_menu_bar_create(resource, &mbar);
316 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
317 PCUT_ASSERT_NOT_NULL(mbar);
318
319 rc = ui_menu_create(mbar, "Test", &menu);
320 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
321 PCUT_ASSERT_NOT_NULL(menu);
322
323 pos.x = 0;
324 pos.y = 0;
325 event.type = POS_PRESS;
326 event.hpos = 0;
327 event.vpos = 0;
328 claimed = ui_menu_pos_event(menu, &pos, &event);
329 PCUT_ASSERT_EQUALS(ui_claimed, claimed);
330
331 ui_menu_bar_destroy(mbar);
332 ui_resource_destroy(resource);
333 dummygc_destroy(dgc);
334}
335
336/** ui_menu_pos_event() outside menu closes it */
337PCUT_TEST(pos_event_outside)
338{
339 dummy_gc_t *dgc;
340 gfx_context_t *gc;
341 ui_resource_t *resource = NULL;
342 ui_menu_bar_t *mbar = NULL;
343 ui_menu_t *menu = NULL;
344 ui_evclaim_t claimed;
345 gfx_coord2_t pos;
346 pos_event_t event;
347 errno_t rc;
348
349 rc = dummygc_create(&dgc);
350 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
351
352 gc = dummygc_get_ctx(dgc);
353
354 rc = ui_resource_create(gc, false, &resource);
355 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
356 PCUT_ASSERT_NOT_NULL(resource);
357
358 rc = ui_menu_bar_create(resource, &mbar);
359 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
360 PCUT_ASSERT_NOT_NULL(mbar);
361
362 rc = ui_menu_create(mbar, "Test", &menu);
363 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
364 PCUT_ASSERT_NOT_NULL(menu);
365
366 pos.x = 0;
367 pos.y = 0;
368 ui_menu_bar_select(mbar, &pos, menu);
369 PCUT_ASSERT_EQUALS(menu, mbar->selected);
370
371 pos.x = 10;
372 pos.y = 0;
373 event.type = POS_PRESS;
374 event.hpos = 0;
375 event.vpos = 0;
376 claimed = ui_menu_pos_event(menu, &pos, &event);
377 PCUT_ASSERT_EQUALS(ui_unclaimed, claimed);
378
379 /* Press event outside menu should close it */
380 PCUT_ASSERT_NULL(mbar->selected);
381
382 ui_menu_bar_destroy(mbar);
383 ui_resource_destroy(resource);
384 dummygc_destroy(dgc);
385}
386
387/** Computing menu geometry */
388PCUT_TEST(get_geom)
389{
390 dummy_gc_t *dgc;
391 gfx_context_t *gc;
392 ui_resource_t *resource = NULL;
393 ui_menu_bar_t *mbar = NULL;
394 ui_menu_t *menu = NULL;
395 ui_menu_geom_t geom;
396 gfx_coord2_t pos;
397 errno_t rc;
398
399 rc = dummygc_create(&dgc);
400 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
401
402 gc = dummygc_get_ctx(dgc);
403
404 rc = ui_resource_create(gc, false, &resource);
405 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
406 PCUT_ASSERT_NOT_NULL(resource);
407
408 rc = ui_menu_bar_create(resource, &mbar);
409 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
410 PCUT_ASSERT_NOT_NULL(mbar);
411
412 rc = ui_menu_create(mbar, "Test", &menu);
413 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
414 PCUT_ASSERT_NOT_NULL(menu);
415
416 pos.x = 0;
417 pos.y = 0;
418 ui_menu_get_geom(menu, &pos, &geom);
419
420 PCUT_ASSERT_INT_EQUALS(0, geom.outer_rect.p0.x);
421 PCUT_ASSERT_INT_EQUALS(0, geom.outer_rect.p0.y);
422 PCUT_ASSERT_INT_EQUALS(8, geom.outer_rect.p1.x);
423 PCUT_ASSERT_INT_EQUALS(8, geom.outer_rect.p1.y);
424 PCUT_ASSERT_INT_EQUALS(4, geom.entries_rect.p0.x);
425 PCUT_ASSERT_INT_EQUALS(4, geom.entries_rect.p0.y);
426 PCUT_ASSERT_INT_EQUALS(4, geom.entries_rect.p1.x);
427 PCUT_ASSERT_INT_EQUALS(4, geom.entries_rect.p1.y);
428
429 ui_menu_bar_destroy(mbar);
430 ui_resource_destroy(resource);
431 dummygc_destroy(dgc);
432}
433
434static void test_expose(void *arg)
435{
436 test_resp_t *resp = (test_resp_t *) arg;
437
438 resp->expose = true;
439}
440
441PCUT_EXPORT(menu);
Note: See TracBrowser for help on using the repository browser.