1 /**************************************************************************
2  *
3  * Copyright (C) 2014 Red Hat Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  **************************************************************************/
24 
25 /*
26  * basic library initialisation, teardown, reset
27  * and context creation tests.
28  */
29 
30 #include <check.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <virglrenderer.h>
34 #include <gbm.h>
35 #include <sys/uio.h>
36 #include "testvirgl.h"
37 #include "virgl_hw.h"
38 struct myinfo_struct {
39   uint32_t test;
40 };
41 
42 struct myinfo_struct mystruct;
43 
44 static struct virgl_renderer_callbacks test_cbs;
45 
START_TEST(virgl_init_no_cbs)46 START_TEST(virgl_init_no_cbs)
47 {
48   int ret;
49   ret = virgl_renderer_init(&mystruct, 0, NULL);
50   ck_assert_int_eq(ret, -1);
51 }
52 END_TEST
53 
START_TEST(virgl_init_no_cookie)54 START_TEST(virgl_init_no_cookie)
55 {
56   int ret;
57   ret = virgl_renderer_init(NULL, 0, &test_cbs);
58   ck_assert_int_eq(ret, -1);
59 }
60 END_TEST
61 
START_TEST(virgl_init_cbs_wrong_ver)62 START_TEST(virgl_init_cbs_wrong_ver)
63 {
64   int ret;
65   struct virgl_renderer_callbacks testcbs;
66   memset(&testcbs, 0, sizeof(testcbs));
67   testcbs.version = VIRGL_RENDERER_CALLBACKS_VERSION + 1;
68   ret = virgl_renderer_init(&mystruct, 0, &testcbs);
69   ck_assert_int_eq(ret, -1);
70 }
71 END_TEST
72 
START_TEST(virgl_init_egl)73 START_TEST(virgl_init_egl)
74 {
75   int ret;
76   test_cbs.version = 1;
77   ret = virgl_renderer_init(&mystruct, VIRGL_RENDERER_USE_EGL, &test_cbs);
78   ck_assert_int_eq(ret, 0);
79   virgl_renderer_cleanup(&mystruct);
80 }
81 
82 END_TEST
83 
START_TEST(virgl_init_egl_create_ctx)84 START_TEST(virgl_init_egl_create_ctx)
85 {
86   int ret;
87   test_cbs.version = 1;
88   ret = virgl_renderer_init(&mystruct, VIRGL_RENDERER_USE_EGL, &test_cbs);
89   ck_assert_int_eq(ret, 0);
90   ret = virgl_renderer_context_create(1, strlen("test1"), "test1");
91   ck_assert_int_eq(ret, 0);
92 
93   virgl_renderer_context_destroy(1);
94   virgl_renderer_cleanup(&mystruct);
95 }
96 END_TEST
97 
START_TEST(virgl_init_egl_create_ctx_0)98 START_TEST(virgl_init_egl_create_ctx_0)
99 {
100   int ret;
101 
102   test_cbs.version = 1;
103   ret = virgl_renderer_init(&mystruct, VIRGL_RENDERER_USE_EGL, &test_cbs);
104   ck_assert_int_eq(ret, 0);
105   ret = virgl_renderer_context_create(0, strlen("test1"), "test1");
106   ck_assert_int_eq(ret, EINVAL);
107 
108   virgl_renderer_cleanup(&mystruct);
109 }
110 END_TEST
111 
START_TEST(virgl_init_egl_destroy_ctx_illegal)112 START_TEST(virgl_init_egl_destroy_ctx_illegal)
113 {
114   int ret;
115   test_cbs.version = 1;
116   ret = virgl_renderer_init(&mystruct, VIRGL_RENDERER_USE_EGL, &test_cbs);
117   ck_assert_int_eq(ret, 0);
118 
119   virgl_renderer_context_destroy(1);
120   virgl_renderer_cleanup(&mystruct);
121 }
122 END_TEST
123 
START_TEST(virgl_init_egl_create_ctx_leak)124 START_TEST(virgl_init_egl_create_ctx_leak)
125 {
126   testvirgl_init_single_ctx();
127 
128   /* don't destroy the context - leak it make sure cleanup catches it */
129   /*virgl_renderer_context_destroy(1);*/
130   virgl_renderer_cleanup(&mystruct);
131 }
132 END_TEST
133 
START_TEST(virgl_init_egl_create_ctx_create_bind_res)134 START_TEST(virgl_init_egl_create_ctx_create_bind_res)
135 {
136   int ret;
137   struct virgl_renderer_resource_create_args res;
138 
139   testvirgl_init_simple_1d_resource(&res, 1);
140 
141   ret = virgl_renderer_resource_create(&res, NULL, 0);
142   ck_assert_int_eq(ret, 0);
143 
144   virgl_renderer_ctx_attach_resource(1, res.handle);
145 
146   virgl_renderer_ctx_detach_resource(1, res.handle);
147 
148   virgl_renderer_resource_unref(1);
149 }
150 END_TEST
151 
START_TEST(virgl_init_egl_create_ctx_create_bind_res_illegal_ctx)152 START_TEST(virgl_init_egl_create_ctx_create_bind_res_illegal_ctx)
153 {
154   int ret;
155   struct virgl_renderer_resource_create_args res;
156 
157   testvirgl_init_simple_1d_resource(&res, 1);
158 
159   ret = virgl_renderer_resource_create(&res, NULL, 0);
160   ck_assert_int_eq(ret, 0);
161 
162   virgl_renderer_ctx_attach_resource(2, res.handle);
163 
164   virgl_renderer_resource_unref(1);
165 }
166 END_TEST
167 
168 
START_TEST(virgl_init_egl_create_ctx_create_bind_res_illegal_res)169 START_TEST(virgl_init_egl_create_ctx_create_bind_res_illegal_res)
170 {
171   int ret;
172   struct virgl_renderer_resource_create_args res;
173 
174   testvirgl_init_simple_1d_resource(&res, 1);
175 
176   ret = virgl_renderer_resource_create(&res, NULL, 0);
177   ck_assert_int_eq(ret, 0);
178 
179   virgl_renderer_ctx_attach_resource(1, 2);
180 
181   virgl_renderer_resource_unref(1);
182 }
183 END_TEST
184 
START_TEST(virgl_init_egl_create_ctx_create_unbind_no_bind)185 START_TEST(virgl_init_egl_create_ctx_create_unbind_no_bind)
186 {
187   int ret;
188   struct virgl_renderer_resource_create_args res;
189 
190   testvirgl_init_simple_1d_resource(&res, 1);
191 
192   ret = virgl_renderer_resource_create(&res, NULL, 0);
193   ck_assert_int_eq(ret, 0);
194 
195   virgl_renderer_ctx_detach_resource(1, res.handle);
196 
197   virgl_renderer_resource_unref(1);
198 }
199 END_TEST
200 
START_TEST(virgl_init_egl_create_ctx_create_unbind_illegal_ctx)201 START_TEST(virgl_init_egl_create_ctx_create_unbind_illegal_ctx)
202 {
203   int ret;
204   struct virgl_renderer_resource_create_args res;
205 
206   testvirgl_init_simple_1d_resource(&res, 1);
207 
208   ret = virgl_renderer_resource_create(&res, NULL, 0);
209   ck_assert_int_eq(ret, 0);
210 
211   virgl_renderer_ctx_detach_resource(2, res.handle);
212 
213   virgl_renderer_resource_unref(1);
214 }
215 END_TEST
216 
217 
START_TEST(virgl_init_egl_create_ctx_create_bind_res_leak)218 START_TEST(virgl_init_egl_create_ctx_create_bind_res_leak)
219 {
220   int ret;
221   struct virgl_renderer_resource_create_args res;
222 
223   testvirgl_init_single_ctx_nr();
224 
225   testvirgl_init_simple_1d_resource(&res, 1);
226 
227   ret = virgl_renderer_resource_create(&res, NULL, 0);
228   ck_assert_int_eq(ret, 0);
229 
230   virgl_renderer_ctx_attach_resource(1, res.handle);
231 
232   /*virgl_renderer_ctx_detach_resource(1, res.handle);*/
233 
234   /*virgl_renderer_resource_unref(1);*/
235   /* don't detach or destroy resource - it should still get cleanedup */
236   testvirgl_fini_single_ctx();
237 }
238 END_TEST
239 
START_TEST(virgl_init_egl_create_ctx_reset)240 START_TEST(virgl_init_egl_create_ctx_reset)
241 {
242   int ret;
243 
244   ret = testvirgl_init_single_ctx();
245   ck_assert_int_eq(ret, 0);
246 
247   virgl_renderer_reset();
248 
249   /* reset should have destroyed the context */
250   ret = virgl_renderer_context_create(1, strlen("test1"), "test1");
251   ck_assert_int_eq(ret, 0);
252   virgl_renderer_cleanup(&mystruct);
253 }
254 END_TEST
255 
START_TEST(virgl_init_get_caps_set0)256 START_TEST(virgl_init_get_caps_set0)
257 {
258   int ret;
259   uint32_t max_ver, max_size;
260 
261   test_cbs.version = 1;
262   ret = virgl_renderer_init(&mystruct, VIRGL_RENDERER_USE_EGL, &test_cbs);
263   ck_assert_int_eq(ret, 0);
264 
265   virgl_renderer_get_cap_set(0, &max_ver, &max_size);
266   ck_assert_int_eq(max_ver, 0);
267   ck_assert_int_eq(max_size, 0);
268 
269   virgl_renderer_cleanup(&mystruct);
270 }
271 END_TEST
272 
START_TEST(virgl_init_get_caps_set1)273 START_TEST(virgl_init_get_caps_set1)
274 {
275   int ret;
276   uint32_t max_ver, max_size;
277   void *caps;
278   test_cbs.version = 1;
279   ret = virgl_renderer_init(&mystruct, VIRGL_RENDERER_USE_EGL, &test_cbs);
280   ck_assert_int_eq(ret, 0);
281 
282   virgl_renderer_get_cap_set(1, &max_ver, &max_size);
283   ck_assert_int_ge(max_ver, 1);
284   ck_assert_int_ne(max_size, 0);
285   ck_assert_int_ge(max_size, sizeof(struct virgl_caps_v1));
286 
287   caps = malloc(max_size);
288 
289   virgl_renderer_fill_caps(0, 0, caps);
290 
291   free(caps);
292   virgl_renderer_cleanup(&mystruct);
293 }
294 END_TEST
295 
START_TEST(virgl_init_get_caps_null)296 START_TEST(virgl_init_get_caps_null)
297 {
298   int ret;
299   uint32_t max_ver, max_size;
300 
301   test_cbs.version = 1;
302   ret = virgl_renderer_init(&mystruct, VIRGL_RENDERER_USE_EGL, &test_cbs);
303   ck_assert_int_eq(ret, 0);
304 
305   virgl_renderer_get_cap_set(1, &max_ver, &max_size);
306   ck_assert_int_ge(max_ver, 1);
307   ck_assert_int_ne(max_size, 0);
308   ck_assert_int_ge(max_size, sizeof(struct virgl_caps_v1));
309 
310   virgl_renderer_fill_caps(0, 0, NULL);
311 
312   virgl_renderer_cleanup(&mystruct);
313 }
314 END_TEST
315 
START_TEST(virgl_test_get_resource_info)316 START_TEST(virgl_test_get_resource_info)
317 {
318   int ret;
319   struct virgl_renderer_resource_create_args res;
320   struct virgl_renderer_resource_info info;
321 
322   testvirgl_init_simple_2d_resource(&res, 1);
323   res.format = VIRGL_FORMAT_B8G8R8X8_UNORM;
324   ret = virgl_renderer_resource_create(&res, NULL, 0);
325   ck_assert_int_eq(ret, 0);
326 
327   virgl_renderer_ctx_attach_resource(1, res.handle);
328 
329   ret = virgl_renderer_resource_get_info(res.handle, &info);
330   ck_assert_int_eq(ret, 0);
331 
332   ck_assert(info.drm_fourcc == GBM_FORMAT_ABGR8888 ||
333             info.drm_fourcc == GBM_FORMAT_ARGB8888);
334   ck_assert_int_eq(info.virgl_format, res.format);
335   ck_assert_int_eq(res.width, info.width);
336   ck_assert_int_eq(res.height, info.height);
337   ck_assert_int_eq(res.depth, info.depth);
338   ck_assert_int_eq(res.flags, info.flags);
339   virgl_renderer_ctx_detach_resource(1, res.handle);
340 
341   virgl_renderer_resource_unref(1);
342 }
343 END_TEST
344 
START_TEST(virgl_test_get_resource_info_no_info)345 START_TEST(virgl_test_get_resource_info_no_info)
346 {
347   int ret;
348   struct virgl_renderer_resource_create_args res;
349 
350   testvirgl_init_simple_1d_resource(&res, 1);
351 
352   ret = virgl_renderer_resource_create(&res, NULL, 0);
353   ck_assert_int_eq(ret, 0);
354 
355   virgl_renderer_ctx_attach_resource(1, res.handle);
356 
357   ret = virgl_renderer_resource_get_info(1, NULL);
358   ck_assert_int_eq(ret, EINVAL);
359 
360   virgl_renderer_ctx_detach_resource(1, res.handle);
361   virgl_renderer_resource_unref(1);
362 }
363 END_TEST
364 
365 
START_TEST(virgl_test_get_resource_info_no_res)366 START_TEST(virgl_test_get_resource_info_no_res)
367 {
368   int ret;
369   struct virgl_renderer_resource_info info;
370 
371   ret = virgl_renderer_resource_get_info(1, &info);
372   ck_assert_int_eq(ret, EINVAL);
373 
374   virgl_renderer_resource_unref(1);
375 }
376 END_TEST
377 
START_TEST(virgl_init_egl_create_ctx_create_attach_res)378 START_TEST(virgl_init_egl_create_ctx_create_attach_res)
379 {
380   int ret;
381   struct virgl_renderer_resource_create_args res;
382   struct iovec iovs[1];
383   struct iovec *iovs_r;
384   int num_r;
385 
386   testvirgl_init_simple_1d_resource(&res, 1);
387 
388   ret = virgl_renderer_resource_create(&res, NULL, 0);
389   ck_assert_int_eq(ret, 0);
390 
391   iovs[0].iov_base = malloc(4096);
392   iovs[0].iov_len = 4096;
393 
394   ret = virgl_renderer_resource_attach_iov(1, iovs, 1);
395   ck_assert_int_eq(ret, 0);
396 
397   virgl_renderer_resource_detach_iov(1, &iovs_r, &num_r);
398 
399   free(iovs[0].iov_base);
400   virgl_renderer_resource_unref(1);
401 }
402 END_TEST
403 
START_TEST(virgl_init_egl_create_ctx_create_attach_res_detach_no_iovs)404 START_TEST(virgl_init_egl_create_ctx_create_attach_res_detach_no_iovs)
405 {
406   int ret;
407   struct virgl_renderer_resource_create_args res;
408   struct iovec iovs[1];
409   int num_r;
410 
411   testvirgl_init_simple_1d_resource(&res, 1);
412 
413   ret = virgl_renderer_resource_create(&res, NULL, 0);
414   ck_assert_int_eq(ret, 0);
415 
416   iovs[0].iov_base = malloc(4096);
417   iovs[0].iov_len = 4096;
418 
419   ret = virgl_renderer_resource_attach_iov(1, iovs, 1);
420   ck_assert_int_eq(ret, 0);
421 
422   virgl_renderer_resource_detach_iov(1, NULL, &num_r);
423 
424   free(iovs[0].iov_base);
425   virgl_renderer_resource_unref(1);
426 }
427 END_TEST
428 
START_TEST(virgl_init_egl_create_ctx_create_attach_res_illegal_res)429 START_TEST(virgl_init_egl_create_ctx_create_attach_res_illegal_res)
430 {
431   int ret;
432   struct iovec iovs[1];
433 
434   test_cbs.version = 1;
435   ret = virgl_renderer_init(&mystruct, VIRGL_RENDERER_USE_EGL, &test_cbs);
436   ck_assert_int_eq(ret, 0);
437 
438   ret = virgl_renderer_resource_attach_iov(1, iovs, 1);
439   ck_assert_int_eq(ret, EINVAL);
440 
441   virgl_renderer_resource_unref(1);
442   virgl_renderer_context_destroy(1);
443   virgl_renderer_cleanup(&mystruct);
444 }
445 END_TEST
446 
virgl_init_suite(void)447 static Suite *virgl_init_suite(void)
448 {
449   Suite *s;
450   TCase *tc_core;
451 
452   s = suite_create("virgl_init");
453   tc_core = tcase_create("init");
454 
455   tcase_add_test(tc_core, virgl_init_no_cbs);
456   tcase_add_test(tc_core, virgl_init_no_cookie);
457   tcase_add_test(tc_core, virgl_init_cbs_wrong_ver);
458   tcase_add_test(tc_core, virgl_init_egl);
459   tcase_add_test(tc_core, virgl_init_egl_create_ctx);
460   tcase_add_test(tc_core, virgl_init_egl_create_ctx_0);
461   tcase_add_test(tc_core, virgl_init_egl_destroy_ctx_illegal);
462   tcase_add_test(tc_core, virgl_init_egl_create_ctx_leak);
463   tcase_add_test(tc_core, virgl_init_egl_create_ctx_reset);
464   tcase_add_test(tc_core, virgl_init_get_caps_set0);
465   tcase_add_test(tc_core, virgl_init_get_caps_set1);
466   tcase_add_test(tc_core, virgl_init_get_caps_null);
467   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_attach_res_illegal_res);
468   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_bind_res_leak);
469 
470   suite_add_tcase(s, tc_core);
471 
472   tc_core = tcase_create("init_std");
473   tcase_add_checked_fixture(tc_core, testvirgl_init_single_ctx_nr, testvirgl_fini_single_ctx);
474   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_bind_res);
475   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_bind_res_illegal_ctx);
476   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_bind_res_illegal_res);
477   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_unbind_no_bind);
478   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_unbind_illegal_ctx);
479 
480   tcase_add_test(tc_core, virgl_test_get_resource_info);
481   tcase_add_test(tc_core, virgl_test_get_resource_info_no_info);
482   tcase_add_test(tc_core, virgl_test_get_resource_info_no_res);
483   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_attach_res);
484   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_attach_res_detach_no_iovs);
485 
486   suite_add_tcase(s, tc_core);
487   return s;
488 
489 }
490 
491 
main(void)492 int main(void)
493 {
494   Suite *s;
495   SRunner *sr;
496   int number_failed;
497 
498   s = virgl_init_suite();
499   sr = srunner_create(s);
500 
501   srunner_run_all(sr, CK_NORMAL);
502   number_failed = srunner_ntests_failed(sr);
503   srunner_free(sr);
504 
505   return number_failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
506 }
507