1 /* Copyright 2020-2021 IGEL Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
21 #include <xf86drmMode.h>
23 #include "lease-manager.h"
25 #include "test-drm-device.h"
26 #include "test-helpers.h"
28 /* CHECK_LEASE_OBJECTS
30 * Checks the list of objects associated with a given lease_index.
31 * Asks the lease manager to create the lease, and checks that
32 * the requested objects are the ones given in the supplied list. */
34 #define CHECK_LEASE_OBJECTS(lease, ...) \
36 lm_lease_grant(g_lm, lease); \
37 uint32_t objs[] = {__VA_ARGS__}; \
38 int nobjs = ARRAY_LEN(objs); \
39 ck_assert_int_eq(drmModeCreateLease_fake.arg2_val, nobjs); \
40 check_uint_array_eq(drmModeCreateLease_fake.arg1_val, objs, \
44 /************** Mock functions *************/
47 FAKE_VALUE_FUNC(drmModeResPtr, drmModeGetResources, int);
48 FAKE_VOID_FUNC(drmModeFreeResources, drmModeResPtr);
49 FAKE_VALUE_FUNC(drmModePlaneResPtr, drmModeGetPlaneResources, int);
50 FAKE_VOID_FUNC(drmModeFreePlaneResources, drmModePlaneResPtr);
52 FAKE_VALUE_FUNC(drmModePlanePtr, drmModeGetPlane, int, uint32_t);
53 FAKE_VOID_FUNC(drmModeFreePlane, drmModePlanePtr);
54 FAKE_VALUE_FUNC(drmModeConnectorPtr, drmModeGetConnector, int, uint32_t);
55 FAKE_VOID_FUNC(drmModeFreeConnector, drmModeConnectorPtr);
56 FAKE_VALUE_FUNC(drmModeEncoderPtr, drmModeGetEncoder, int, uint32_t);
57 FAKE_VOID_FUNC(drmModeFreeEncoder, drmModeEncoderPtr);
59 FAKE_VALUE_FUNC(int, drmModeCreateLease, int, const uint32_t *, int, int,
61 FAKE_VALUE_FUNC(int, drmModeRevokeLease, int, uint32_t);
63 /************** Test fixutre functions *************************/
64 struct lm *g_lm = NULL;
66 static void test_setup(void)
68 RESET_FAKE(drmModeGetResources);
69 RESET_FAKE(drmModeFreeResources);
70 RESET_FAKE(drmModeGetPlaneResources);
71 RESET_FAKE(drmModeFreePlaneResources);
73 RESET_FAKE(drmModeGetPlane);
74 RESET_FAKE(drmModeFreePlane);
75 RESET_FAKE(drmModeGetConnector);
76 RESET_FAKE(drmModeFreeConnector);
77 RESET_FAKE(drmModeGetEncoder);
78 RESET_FAKE(drmModeFreeEncoder);
80 RESET_FAKE(drmModeCreateLease);
81 RESET_FAKE(drmModeRevokeLease);
83 drmModeGetResources_fake.return_val = TEST_DEVICE_RESOURCES;
84 drmModeGetPlaneResources_fake.return_val = TEST_DEVICE_PLANE_RESOURCES;
86 drmModeGetPlane_fake.custom_fake = get_plane;
87 drmModeGetConnector_fake.custom_fake = get_connector;
88 drmModeGetEncoder_fake.custom_fake = get_encoder;
89 drmModeCreateLease_fake.custom_fake = create_lease;
91 ck_assert_msg(g_lm == NULL,
92 "Lease manager context not clear at start of test");
95 static void test_shutdown(void)
97 reset_drm_test_device();
102 static struct lease_handle **create_leases(int num_leases,
103 struct lease_config *configs)
107 lm_create_with_config(TEST_DRM_DEVICE, num_leases, configs);
109 g_lm = lm_create(TEST_DRM_DEVICE);
111 ck_assert_ptr_ne(g_lm, NULL);
113 struct lease_handle **handles;
114 ck_assert_int_eq(num_leases, lm_get_lease_handles(g_lm, &handles));
115 ck_assert_ptr_ne(handles, NULL);
120 /************** Resource enumeration tests *************/
122 /* These tests verify that the lease manager correctly assigns
123 * DRM resources to thier respective leases. In some cases
124 * the lease manager must choose which resources to include in
125 * each lease, so these tests verify that a valid (but not
126 * necessarily optimal) choice is made.
129 /* all_outputs_connected
131 * Test details: Create leases when all crtc/encoder/connector paths are
134 * Expected results: Leases are created for the currently connected sets of
137 START_TEST(all_outputs_connected)
139 int out_cnt = 2, plane_cnt = 0;
141 setup_layout_simple_test_device(out_cnt, plane_cnt);
143 struct lease_handle **handles = create_leases(out_cnt, NULL);
145 CHECK_LEASE_OBJECTS(handles[0], CRTC_ID(0), CONNECTOR_ID(0));
146 CHECK_LEASE_OBJECTS(handles[1], CRTC_ID(1), CONNECTOR_ID(1));
150 /* no_outputs_connected
152 * Test details: Create leases when no crtc/encoder/connector paths are
155 * Expected results: Available resources are divided between the leases.
156 * The same resource should not appear in multiple leases.
158 START_TEST(no_outputs_connected)
160 int out_cnt = 2, plane_cnt = 0;
163 setup_drm_test_device(out_cnt, out_cnt, out_cnt, plane_cnt), true);
165 drmModeConnector connectors[] = {
166 CONNECTOR(CONNECTOR_ID(0), 0, &ENCODER_ID(0), 1),
167 CONNECTOR(CONNECTOR_ID(1), 0, &ENCODER_ID(1), 1),
170 drmModeEncoder encoders[] = {
171 ENCODER(ENCODER_ID(0), 0, 0x2),
172 ENCODER(ENCODER_ID(1), 0, 0x3),
175 setup_test_device_layout(connectors, encoders, NULL);
177 g_lm = lm_create(TEST_DRM_DEVICE);
178 ck_assert_ptr_ne(g_lm, NULL);
180 struct lease_handle **handles = create_leases(out_cnt, NULL);
182 CHECK_LEASE_OBJECTS(handles[0], CRTC_ID(1), CONNECTOR_ID(0));
183 CHECK_LEASE_OBJECTS(handles[1], CRTC_ID(0), CONNECTOR_ID(1));
187 /* some_outputs_connected */
188 /* Test details: Create leases when one output is connected and one is not.
189 * Expected results: Currently connected resources should be added to
191 * The non-connected resources should be added to a second
194 START_TEST(some_outputs_connected)
196 int out_cnt = 2, plane_cnt = 0;
199 setup_drm_test_device(out_cnt, out_cnt, out_cnt, plane_cnt), true);
201 drmModeConnector connectors[] = {
202 CONNECTOR(CONNECTOR_ID(0), ENCODER_ID(0), &ENCODER_ID(0), 1),
203 CONNECTOR(CONNECTOR_ID(1), 0, &ENCODER_ID(1), 1),
206 drmModeEncoder encoders[] = {
207 ENCODER(ENCODER_ID(0), CRTC_ID(0), 0x3),
208 ENCODER(ENCODER_ID(1), 0, 0x3),
211 setup_test_device_layout(connectors, encoders, NULL);
213 struct lease_handle **handles = create_leases(out_cnt, NULL);
215 CHECK_LEASE_OBJECTS(handles[0], CRTC_ID(0), CONNECTOR_ID(0));
216 CHECK_LEASE_OBJECTS(handles[1], CRTC_ID(1), CONNECTOR_ID(1));
220 /* fewer_crtcs_than_connectors */
221 /* Test details: Create leases on a system with more connectors than CRTCs
222 * Expected results: Number of leases generated should correspond to number of
224 * Leases contain one valid connector for each CRTC.
226 START_TEST(fewer_crtcs_than_connectors)
228 int out_cnt = 3, plane_cnt = 0, crtc_cnt = 2;
231 setup_drm_test_device(crtc_cnt, out_cnt, out_cnt, plane_cnt), true);
233 drmModeConnector connectors[] = {
234 CONNECTOR(CONNECTOR_ID(0), 0, &ENCODER_ID(0), 1),
235 CONNECTOR(CONNECTOR_ID(1), 0, &ENCODER_ID(1), 1),
236 CONNECTOR(CONNECTOR_ID(2), 0, &ENCODER_ID(2), 1),
239 drmModeEncoder encoders[] = {
240 ENCODER(ENCODER_ID(0), 0, 0x3),
241 ENCODER(ENCODER_ID(1), 0, 0x1),
242 ENCODER(ENCODER_ID(2), 0, 0x3),
245 setup_test_device_layout(connectors, encoders, NULL);
247 struct lease_handle **handles = create_leases(crtc_cnt, NULL);
249 CHECK_LEASE_OBJECTS(handles[0], CRTC_ID(0), CONNECTOR_ID(0));
250 CHECK_LEASE_OBJECTS(handles[1], CRTC_ID(1), CONNECTOR_ID(2));
254 /* separate_overlay_planes_by_crtc */
255 /* Test details: Add overlay planes to leases. Each plane is tied to a
257 * Expected results: The leases contain all of the planes for connected to
258 * each CRTC and no others.
260 START_TEST(separate_overlay_planes_by_crtc)
263 int out_cnt = 2, plane_cnt = 3;
265 setup_layout_simple_test_device(out_cnt, plane_cnt);
267 struct lease_handle **handles = create_leases(out_cnt, NULL);
269 CHECK_LEASE_OBJECTS(handles[0], PLANE_ID(0), PLANE_ID(2), CRTC_ID(0),
271 CHECK_LEASE_OBJECTS(handles[1], PLANE_ID(1), CRTC_ID(1),
276 /* reject_planes_shared_between_multiple_crtcs */
277 /* Test details: Add overlay planes to leases. Some planes are shared between
279 * Expected results: The leases contain all of the unique planes for each CRTC.
280 * Planes that can be used on multiple CRTCs are not included
283 START_TEST(reject_planes_shared_between_multiple_crtcs)
286 int out_cnt = 2, plane_cnt = 3;
289 setup_drm_test_device(out_cnt, out_cnt, out_cnt, plane_cnt), true);
291 drmModeConnector connectors[] = {
292 CONNECTOR(CONNECTOR_ID(0), ENCODER_ID(0), &ENCODER_ID(0), 1),
293 CONNECTOR(CONNECTOR_ID(1), ENCODER_ID(1), &ENCODER_ID(1), 1),
296 drmModeEncoder encoders[] = {
297 ENCODER(ENCODER_ID(0), CRTC_ID(0), 0x1),
298 ENCODER(ENCODER_ID(1), CRTC_ID(1), 0x2),
301 drmModePlane planes[] = {
302 PLANE(PLANE_ID(0), 0x2),
303 PLANE(PLANE_ID(1), 0x1),
304 PLANE(PLANE_ID(2), 0x3),
307 setup_test_device_layout(connectors, encoders, planes);
309 struct lease_handle **handles = create_leases(out_cnt, NULL);
311 CHECK_LEASE_OBJECTS(handles[0], PLANE_ID(1), CRTC_ID(0),
313 CHECK_LEASE_OBJECTS(handles[1], PLANE_ID(0), CRTC_ID(1),
318 static void add_connector_enum_tests(Suite *s)
320 TCase *tc = tcase_create("Resource enumeration");
322 tcase_add_checked_fixture(tc, test_setup, test_shutdown);
324 tcase_add_test(tc, all_outputs_connected);
325 tcase_add_test(tc, no_outputs_connected);
326 tcase_add_test(tc, fewer_crtcs_than_connectors);
327 tcase_add_test(tc, some_outputs_connected);
328 tcase_add_test(tc, separate_overlay_planes_by_crtc);
329 tcase_add_test(tc, reject_planes_shared_between_multiple_crtcs);
330 suite_add_tcase(s, tc);
333 /************** Lease management tests *************/
335 /* create_and_revoke_lease */
336 /* Test details: Create leases and revoke them.
337 * Expected results: drmModeRevokeLease() is called with the correct leasee_id.
339 START_TEST(create_and_revoke_lease)
341 int lease_cnt = 2, plane_cnt = 0;
343 setup_layout_simple_test_device(lease_cnt, plane_cnt);
345 struct lease_handle **handles = create_leases(lease_cnt, NULL);
347 for (int i = 0; i < lease_cnt; i++) {
348 ck_assert_int_ge(lm_lease_grant(g_lm, handles[i]), 0);
349 lm_lease_revoke(g_lm, handles[i]);
352 ck_assert_int_eq(drmModeRevokeLease_fake.call_count, lease_cnt);
354 for (int i = 0; i < lease_cnt; i++) {
355 ck_assert_int_eq(drmModeRevokeLease_fake.arg1_history[i],
361 static void add_lease_management_tests(Suite *s)
363 TCase *tc = tcase_create("Lease management");
365 tcase_add_checked_fixture(tc, test_setup, test_shutdown);
367 tcase_add_test(tc, create_and_revoke_lease);
368 suite_add_tcase(s, tc);
377 s = suite_create("DLM lease manager tests");
379 add_connector_enum_tests(s);
380 add_lease_management_tests(s);
382 sr = srunner_create(s);
383 srunner_run_all(sr, CK_NORMAL);
384 number_failed = srunner_ntests_failed(sr);
386 return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;