1 // SPDX-License-Identifier: GPL-2.0+
2
3 #include <kunit/test.h>
4
5 #include "../vkms_config.h"
6
7 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
8
vkms_config_get_num_planes(struct vkms_config * config)9 static size_t vkms_config_get_num_planes(struct vkms_config *config)
10 {
11 struct vkms_config_plane *plane_cfg;
12 size_t count = 0;
13
14 vkms_config_for_each_plane(config, plane_cfg)
15 count++;
16
17 return count;
18 }
19
vkms_config_get_num_encoders(struct vkms_config * config)20 static size_t vkms_config_get_num_encoders(struct vkms_config *config)
21 {
22 struct vkms_config_encoder *encoder_cfg;
23 size_t count = 0;
24
25 vkms_config_for_each_encoder(config, encoder_cfg)
26 count++;
27
28 return count;
29 }
30
vkms_config_get_num_connectors(struct vkms_config * config)31 static size_t vkms_config_get_num_connectors(struct vkms_config *config)
32 {
33 struct vkms_config_connector *connector_cfg;
34 size_t count = 0;
35
36 vkms_config_for_each_connector(config, connector_cfg)
37 count++;
38
39 return count;
40 }
41
get_first_plane(struct vkms_config * config)42 static struct vkms_config_plane *get_first_plane(struct vkms_config *config)
43 {
44 struct vkms_config_plane *plane_cfg;
45
46 vkms_config_for_each_plane(config, plane_cfg)
47 return plane_cfg;
48
49 return NULL;
50 }
51
get_first_crtc(struct vkms_config * config)52 static struct vkms_config_crtc *get_first_crtc(struct vkms_config *config)
53 {
54 struct vkms_config_crtc *crtc_cfg;
55
56 vkms_config_for_each_crtc(config, crtc_cfg)
57 return crtc_cfg;
58
59 return NULL;
60 }
61
get_first_encoder(struct vkms_config * config)62 static struct vkms_config_encoder *get_first_encoder(struct vkms_config *config)
63 {
64 struct vkms_config_encoder *encoder_cfg;
65
66 vkms_config_for_each_encoder(config, encoder_cfg)
67 return encoder_cfg;
68
69 return NULL;
70 }
71
get_first_connector(struct vkms_config * config)72 static struct vkms_config_connector *get_first_connector(struct vkms_config *config)
73 {
74 struct vkms_config_connector *connector_cfg;
75
76 vkms_config_for_each_connector(config, connector_cfg)
77 return connector_cfg;
78
79 return NULL;
80 }
81
82 struct default_config_case {
83 bool enable_cursor;
84 bool enable_writeback;
85 bool enable_overlay;
86 };
87
vkms_config_test_empty_config(struct kunit * test)88 static void vkms_config_test_empty_config(struct kunit *test)
89 {
90 struct vkms_config *config;
91 const char *dev_name = "test";
92
93 config = vkms_config_create(dev_name);
94 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
95
96 /* The dev_name string and the config have different lifetimes */
97 dev_name = NULL;
98 KUNIT_EXPECT_STREQ(test, vkms_config_get_device_name(config), "test");
99
100 KUNIT_EXPECT_EQ(test, vkms_config_get_num_planes(config), 0);
101 KUNIT_EXPECT_EQ(test, vkms_config_get_num_crtcs(config), 0);
102 KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 0);
103 KUNIT_EXPECT_EQ(test, vkms_config_get_num_connectors(config), 0);
104
105 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
106
107 vkms_config_destroy(config);
108 }
109
110 static struct default_config_case default_config_cases[] = {
111 { false, false, false },
112 { true, false, false },
113 { true, true, false },
114 { true, false, true },
115 { false, true, false },
116 { false, true, true },
117 { false, false, true },
118 { true, true, true },
119 };
120
121 KUNIT_ARRAY_PARAM(default_config, default_config_cases, NULL);
122
vkms_config_test_default_config(struct kunit * test)123 static void vkms_config_test_default_config(struct kunit *test)
124 {
125 const struct default_config_case *params = test->param_value;
126 struct vkms_config *config;
127 struct vkms_config_plane *plane_cfg;
128 struct vkms_config_crtc *crtc_cfg;
129 int n_primaries = 0;
130 int n_cursors = 0;
131 int n_overlays = 0;
132
133 config = vkms_config_default_create(params->enable_cursor,
134 params->enable_writeback,
135 params->enable_overlay);
136 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
137
138 /* Planes */
139 vkms_config_for_each_plane(config, plane_cfg) {
140 switch (vkms_config_plane_get_type(plane_cfg)) {
141 case DRM_PLANE_TYPE_PRIMARY:
142 n_primaries++;
143 break;
144 case DRM_PLANE_TYPE_CURSOR:
145 n_cursors++;
146 break;
147 case DRM_PLANE_TYPE_OVERLAY:
148 n_overlays++;
149 break;
150 default:
151 KUNIT_FAIL_AND_ABORT(test, "Unknown plane type");
152 }
153 }
154 KUNIT_EXPECT_EQ(test, n_primaries, 1);
155 KUNIT_EXPECT_EQ(test, n_cursors, params->enable_cursor ? 1 : 0);
156 KUNIT_EXPECT_EQ(test, n_overlays, params->enable_overlay ? 8 : 0);
157
158 /* CRTCs */
159 KUNIT_EXPECT_EQ(test, vkms_config_get_num_crtcs(config), 1);
160
161 crtc_cfg = get_first_crtc(config);
162 KUNIT_EXPECT_EQ(test, vkms_config_crtc_get_writeback(crtc_cfg),
163 params->enable_writeback);
164
165 vkms_config_for_each_plane(config, plane_cfg) {
166 struct vkms_config_crtc *possible_crtc;
167 int n_possible_crtcs = 0;
168 unsigned long idx = 0;
169
170 vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) {
171 KUNIT_EXPECT_PTR_EQ(test, crtc_cfg, possible_crtc);
172 n_possible_crtcs++;
173 }
174 KUNIT_EXPECT_EQ(test, n_possible_crtcs, 1);
175 }
176
177 /* Encoders */
178 KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 1);
179
180 /* Connectors */
181 KUNIT_EXPECT_EQ(test, vkms_config_get_num_connectors(config), 1);
182
183 KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
184
185 vkms_config_destroy(config);
186 }
187
vkms_config_test_get_planes(struct kunit * test)188 static void vkms_config_test_get_planes(struct kunit *test)
189 {
190 struct vkms_config *config;
191 struct vkms_config_plane *plane_cfg;
192 struct vkms_config_plane *plane_cfg1, *plane_cfg2;
193 int n_planes = 0;
194
195 config = vkms_config_create("test");
196 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
197
198 vkms_config_for_each_plane(config, plane_cfg)
199 n_planes++;
200 KUNIT_ASSERT_EQ(test, n_planes, 0);
201
202 plane_cfg1 = vkms_config_create_plane(config);
203 vkms_config_for_each_plane(config, plane_cfg) {
204 n_planes++;
205 if (plane_cfg != plane_cfg1)
206 KUNIT_FAIL(test, "Unexpected plane");
207 }
208 KUNIT_ASSERT_EQ(test, n_planes, 1);
209 n_planes = 0;
210
211 plane_cfg2 = vkms_config_create_plane(config);
212 vkms_config_for_each_plane(config, plane_cfg) {
213 n_planes++;
214 if (plane_cfg != plane_cfg1 && plane_cfg != plane_cfg2)
215 KUNIT_FAIL(test, "Unexpected plane");
216 }
217 KUNIT_ASSERT_EQ(test, n_planes, 2);
218 n_planes = 0;
219
220 vkms_config_destroy_plane(plane_cfg1);
221 vkms_config_for_each_plane(config, plane_cfg) {
222 n_planes++;
223 if (plane_cfg != plane_cfg2)
224 KUNIT_FAIL(test, "Unexpected plane");
225 }
226 KUNIT_ASSERT_EQ(test, n_planes, 1);
227
228 vkms_config_destroy(config);
229 }
230
vkms_config_test_get_crtcs(struct kunit * test)231 static void vkms_config_test_get_crtcs(struct kunit *test)
232 {
233 struct vkms_config *config;
234 struct vkms_config_crtc *crtc_cfg;
235 struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
236
237 config = vkms_config_create("test");
238 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
239
240 KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 0);
241 vkms_config_for_each_crtc(config, crtc_cfg)
242 KUNIT_FAIL(test, "Unexpected CRTC");
243
244 crtc_cfg1 = vkms_config_create_crtc(config);
245 KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 1);
246 vkms_config_for_each_crtc(config, crtc_cfg) {
247 if (crtc_cfg != crtc_cfg1)
248 KUNIT_FAIL(test, "Unexpected CRTC");
249 }
250
251 crtc_cfg2 = vkms_config_create_crtc(config);
252 KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 2);
253 vkms_config_for_each_crtc(config, crtc_cfg) {
254 if (crtc_cfg != crtc_cfg1 && crtc_cfg != crtc_cfg2)
255 KUNIT_FAIL(test, "Unexpected CRTC");
256 }
257
258 vkms_config_destroy_crtc(config, crtc_cfg2);
259 KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 1);
260 vkms_config_for_each_crtc(config, crtc_cfg) {
261 if (crtc_cfg != crtc_cfg1)
262 KUNIT_FAIL(test, "Unexpected CRTC");
263 }
264
265 vkms_config_destroy(config);
266 }
267
vkms_config_test_get_encoders(struct kunit * test)268 static void vkms_config_test_get_encoders(struct kunit *test)
269 {
270 struct vkms_config *config;
271 struct vkms_config_encoder *encoder_cfg;
272 struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2;
273 int n_encoders = 0;
274
275 config = vkms_config_create("test");
276 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
277
278 vkms_config_for_each_encoder(config, encoder_cfg)
279 n_encoders++;
280 KUNIT_ASSERT_EQ(test, n_encoders, 0);
281
282 encoder_cfg1 = vkms_config_create_encoder(config);
283 vkms_config_for_each_encoder(config, encoder_cfg) {
284 n_encoders++;
285 if (encoder_cfg != encoder_cfg1)
286 KUNIT_FAIL(test, "Unexpected encoder");
287 }
288 KUNIT_ASSERT_EQ(test, n_encoders, 1);
289 n_encoders = 0;
290
291 encoder_cfg2 = vkms_config_create_encoder(config);
292 vkms_config_for_each_encoder(config, encoder_cfg) {
293 n_encoders++;
294 if (encoder_cfg != encoder_cfg1 && encoder_cfg != encoder_cfg2)
295 KUNIT_FAIL(test, "Unexpected encoder");
296 }
297 KUNIT_ASSERT_EQ(test, n_encoders, 2);
298 n_encoders = 0;
299
300 vkms_config_destroy_encoder(config, encoder_cfg2);
301 vkms_config_for_each_encoder(config, encoder_cfg) {
302 n_encoders++;
303 if (encoder_cfg != encoder_cfg1)
304 KUNIT_FAIL(test, "Unexpected encoder");
305 }
306 KUNIT_ASSERT_EQ(test, n_encoders, 1);
307 n_encoders = 0;
308
309 vkms_config_destroy(config);
310 }
311
vkms_config_test_get_connectors(struct kunit * test)312 static void vkms_config_test_get_connectors(struct kunit *test)
313 {
314 struct vkms_config *config;
315 struct vkms_config_connector *connector_cfg;
316 struct vkms_config_connector *connector_cfg1, *connector_cfg2;
317 int n_connectors = 0;
318
319 config = vkms_config_create("test");
320 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
321
322 vkms_config_for_each_connector(config, connector_cfg)
323 n_connectors++;
324 KUNIT_ASSERT_EQ(test, n_connectors, 0);
325
326 connector_cfg1 = vkms_config_create_connector(config);
327 vkms_config_for_each_connector(config, connector_cfg) {
328 n_connectors++;
329 if (connector_cfg != connector_cfg1)
330 KUNIT_FAIL(test, "Unexpected connector");
331 }
332 KUNIT_ASSERT_EQ(test, n_connectors, 1);
333 n_connectors = 0;
334
335 connector_cfg2 = vkms_config_create_connector(config);
336 vkms_config_for_each_connector(config, connector_cfg) {
337 n_connectors++;
338 if (connector_cfg != connector_cfg1 &&
339 connector_cfg != connector_cfg2)
340 KUNIT_FAIL(test, "Unexpected connector");
341 }
342 KUNIT_ASSERT_EQ(test, n_connectors, 2);
343 n_connectors = 0;
344
345 vkms_config_destroy_connector(connector_cfg2);
346 vkms_config_for_each_connector(config, connector_cfg) {
347 n_connectors++;
348 if (connector_cfg != connector_cfg1)
349 KUNIT_FAIL(test, "Unexpected connector");
350 }
351 KUNIT_ASSERT_EQ(test, n_connectors, 1);
352 n_connectors = 0;
353
354 vkms_config_destroy(config);
355 }
356
vkms_config_test_invalid_plane_number(struct kunit * test)357 static void vkms_config_test_invalid_plane_number(struct kunit *test)
358 {
359 struct vkms_config *config;
360 struct vkms_config_plane *plane_cfg;
361 int n;
362
363 config = vkms_config_default_create(false, false, false);
364 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
365
366 /* Invalid: No planes */
367 plane_cfg = get_first_plane(config);
368 vkms_config_destroy_plane(plane_cfg);
369 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
370
371 /* Invalid: Too many planes */
372 for (n = 0; n <= 32; n++)
373 vkms_config_create_plane(config);
374
375 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
376
377 vkms_config_destroy(config);
378 }
379
vkms_config_test_valid_plane_type(struct kunit * test)380 static void vkms_config_test_valid_plane_type(struct kunit *test)
381 {
382 struct vkms_config *config;
383 struct vkms_config_plane *plane_cfg;
384 struct vkms_config_crtc *crtc_cfg;
385 struct vkms_config_encoder *encoder_cfg;
386 int err;
387
388 config = vkms_config_default_create(false, false, false);
389 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
390
391 plane_cfg = get_first_plane(config);
392 vkms_config_destroy_plane(plane_cfg);
393
394 crtc_cfg = get_first_crtc(config);
395
396 /* Invalid: No primary plane */
397 plane_cfg = vkms_config_create_plane(config);
398 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
399 err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
400 KUNIT_EXPECT_EQ(test, err, 0);
401 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
402
403 /* Invalid: Multiple primary planes */
404 plane_cfg = vkms_config_create_plane(config);
405 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
406 err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
407 KUNIT_EXPECT_EQ(test, err, 0);
408
409 plane_cfg = vkms_config_create_plane(config);
410 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
411 err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
412 KUNIT_EXPECT_EQ(test, err, 0);
413
414 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
415
416 /* Valid: One primary plane */
417 vkms_config_destroy_plane(plane_cfg);
418 KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
419
420 /* Invalid: Multiple cursor planes */
421 plane_cfg = vkms_config_create_plane(config);
422 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR);
423 err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
424 KUNIT_EXPECT_EQ(test, err, 0);
425
426 plane_cfg = vkms_config_create_plane(config);
427 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR);
428 err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
429 KUNIT_EXPECT_EQ(test, err, 0);
430
431 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
432
433 /* Valid: One primary and one cursor plane */
434 vkms_config_destroy_plane(plane_cfg);
435 KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
436
437 /* Invalid: Second CRTC without primary plane */
438 crtc_cfg = vkms_config_create_crtc(config);
439 encoder_cfg = vkms_config_create_encoder(config);
440 err = vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg);
441 KUNIT_EXPECT_EQ(test, err, 0);
442 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
443
444 /* Valid: Second CRTC with a primary plane */
445 plane_cfg = vkms_config_create_plane(config);
446 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
447 err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
448 KUNIT_EXPECT_EQ(test, err, 0);
449 KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
450
451 vkms_config_destroy(config);
452 }
453
vkms_config_test_valid_plane_possible_crtcs(struct kunit * test)454 static void vkms_config_test_valid_plane_possible_crtcs(struct kunit *test)
455 {
456 struct vkms_config *config;
457 struct vkms_config_plane *plane_cfg;
458 struct vkms_config_crtc *crtc_cfg;
459
460 config = vkms_config_default_create(false, false, false);
461 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
462
463 plane_cfg = get_first_plane(config);
464 crtc_cfg = get_first_crtc(config);
465
466 /* Invalid: Primary plane without a possible CRTC */
467 vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg);
468 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
469
470 vkms_config_destroy(config);
471 }
472
vkms_config_test_invalid_crtc_number(struct kunit * test)473 static void vkms_config_test_invalid_crtc_number(struct kunit *test)
474 {
475 struct vkms_config *config;
476 struct vkms_config_crtc *crtc_cfg;
477 int n;
478
479 config = vkms_config_default_create(false, false, false);
480 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
481
482 /* Invalid: No CRTCs */
483 crtc_cfg = get_first_crtc(config);
484 vkms_config_destroy_crtc(config, crtc_cfg);
485 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
486
487 /* Invalid: Too many CRTCs */
488 for (n = 0; n <= 32; n++)
489 vkms_config_create_crtc(config);
490
491 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
492
493 vkms_config_destroy(config);
494 }
495
vkms_config_test_invalid_encoder_number(struct kunit * test)496 static void vkms_config_test_invalid_encoder_number(struct kunit *test)
497 {
498 struct vkms_config *config;
499 struct vkms_config_encoder *encoder_cfg;
500 int n;
501
502 config = vkms_config_default_create(false, false, false);
503 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
504
505 /* Invalid: No encoders */
506 encoder_cfg = get_first_encoder(config);
507 vkms_config_destroy_encoder(config, encoder_cfg);
508 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
509
510 /* Invalid: Too many encoders */
511 for (n = 0; n <= 32; n++)
512 vkms_config_create_encoder(config);
513
514 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
515
516 vkms_config_destroy(config);
517 }
518
vkms_config_test_valid_encoder_possible_crtcs(struct kunit * test)519 static void vkms_config_test_valid_encoder_possible_crtcs(struct kunit *test)
520 {
521 struct vkms_config *config;
522 struct vkms_config_plane *plane_cfg;
523 struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
524 struct vkms_config_encoder *encoder_cfg;
525 int err;
526
527 config = vkms_config_default_create(false, false, false);
528 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
529
530 crtc_cfg1 = get_first_crtc(config);
531
532 /* Invalid: Encoder without a possible CRTC */
533 encoder_cfg = vkms_config_create_encoder(config);
534 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
535
536 /* Valid: Second CRTC with shared encoder */
537 crtc_cfg2 = vkms_config_create_crtc(config);
538
539 plane_cfg = vkms_config_create_plane(config);
540 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
541 err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg2);
542 KUNIT_EXPECT_EQ(test, err, 0);
543
544 err = vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg1);
545 KUNIT_EXPECT_EQ(test, err, 0);
546
547 err = vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg2);
548 KUNIT_EXPECT_EQ(test, err, 0);
549
550 KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
551
552 /* Invalid: Second CRTC without encoders */
553 vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg2);
554 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
555
556 /* Valid: First CRTC with 2 possible encoder */
557 vkms_config_destroy_plane(plane_cfg);
558 vkms_config_destroy_crtc(config, crtc_cfg2);
559 KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
560
561 vkms_config_destroy(config);
562 }
563
vkms_config_test_invalid_connector_number(struct kunit * test)564 static void vkms_config_test_invalid_connector_number(struct kunit *test)
565 {
566 struct vkms_config *config;
567 struct vkms_config_connector *connector_cfg;
568 int n;
569
570 config = vkms_config_default_create(false, false, false);
571 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
572
573 /* Invalid: No connectors */
574 connector_cfg = get_first_connector(config);
575 vkms_config_destroy_connector(connector_cfg);
576 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
577
578 /* Invalid: Too many connectors */
579 for (n = 0; n <= 32; n++)
580 connector_cfg = vkms_config_create_connector(config);
581
582 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
583
584 vkms_config_destroy(config);
585 }
586
vkms_config_test_valid_connector_possible_encoders(struct kunit * test)587 static void vkms_config_test_valid_connector_possible_encoders(struct kunit *test)
588 {
589 struct vkms_config *config;
590 struct vkms_config_encoder *encoder_cfg;
591 struct vkms_config_connector *connector_cfg;
592
593 config = vkms_config_default_create(false, false, false);
594 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
595
596 encoder_cfg = get_first_encoder(config);
597 connector_cfg = get_first_connector(config);
598
599 /* Invalid: Connector without a possible encoder */
600 vkms_config_connector_detach_encoder(connector_cfg, encoder_cfg);
601 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
602
603 vkms_config_destroy(config);
604 }
605
vkms_config_test_attach_different_configs(struct kunit * test)606 static void vkms_config_test_attach_different_configs(struct kunit *test)
607 {
608 struct vkms_config *config1, *config2;
609 struct vkms_config_plane *plane_cfg1, *plane_cfg2;
610 struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
611 struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2;
612 struct vkms_config_connector *connector_cfg1, *connector_cfg2;
613 int err;
614
615 config1 = vkms_config_create("test1");
616 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config1);
617
618 config2 = vkms_config_create("test2");
619 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config2);
620
621 plane_cfg1 = vkms_config_create_plane(config1);
622 crtc_cfg1 = vkms_config_create_crtc(config1);
623 encoder_cfg1 = vkms_config_create_encoder(config1);
624 connector_cfg1 = vkms_config_create_connector(config1);
625
626 plane_cfg2 = vkms_config_create_plane(config2);
627 crtc_cfg2 = vkms_config_create_crtc(config2);
628 encoder_cfg2 = vkms_config_create_encoder(config2);
629 connector_cfg2 = vkms_config_create_connector(config2);
630
631 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg1);
632 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg2);
633 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg1);
634 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2);
635 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg1);
636 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg2);
637 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector_cfg1);
638 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector_cfg2);
639
640 err = vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg2);
641 KUNIT_EXPECT_NE(test, err, 0);
642 err = vkms_config_plane_attach_crtc(plane_cfg2, crtc_cfg1);
643 KUNIT_EXPECT_NE(test, err, 0);
644
645 err = vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg2);
646 KUNIT_EXPECT_NE(test, err, 0);
647 err = vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg1);
648 KUNIT_EXPECT_NE(test, err, 0);
649
650 err = vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg2);
651 KUNIT_EXPECT_NE(test, err, 0);
652 err = vkms_config_connector_attach_encoder(connector_cfg2, encoder_cfg1);
653 KUNIT_EXPECT_NE(test, err, 0);
654
655 vkms_config_destroy(config1);
656 vkms_config_destroy(config2);
657 }
658
vkms_config_test_plane_attach_crtc(struct kunit * test)659 static void vkms_config_test_plane_attach_crtc(struct kunit *test)
660 {
661 struct vkms_config *config;
662 struct vkms_config_plane *overlay_cfg;
663 struct vkms_config_plane *primary_cfg;
664 struct vkms_config_plane *cursor_cfg;
665 struct vkms_config_crtc *crtc_cfg;
666 int err;
667
668 config = vkms_config_create("test");
669 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
670
671 overlay_cfg = vkms_config_create_plane(config);
672 vkms_config_plane_set_type(overlay_cfg, DRM_PLANE_TYPE_OVERLAY);
673 primary_cfg = vkms_config_create_plane(config);
674 vkms_config_plane_set_type(primary_cfg, DRM_PLANE_TYPE_PRIMARY);
675 cursor_cfg = vkms_config_create_plane(config);
676 vkms_config_plane_set_type(cursor_cfg, DRM_PLANE_TYPE_CURSOR);
677
678 crtc_cfg = vkms_config_create_crtc(config);
679
680 /* No primary or cursor planes */
681 KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg));
682 KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg));
683
684 /* Overlay plane, but no primary or cursor planes */
685 err = vkms_config_plane_attach_crtc(overlay_cfg, crtc_cfg);
686 KUNIT_EXPECT_EQ(test, err, 0);
687 KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg));
688 KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg));
689
690 /* Primary plane, attaching it twice must fail */
691 err = vkms_config_plane_attach_crtc(primary_cfg, crtc_cfg);
692 KUNIT_EXPECT_EQ(test, err, 0);
693 err = vkms_config_plane_attach_crtc(primary_cfg, crtc_cfg);
694 KUNIT_EXPECT_NE(test, err, 0);
695 KUNIT_EXPECT_PTR_EQ(test,
696 vkms_config_crtc_primary_plane(config, crtc_cfg),
697 primary_cfg);
698 KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg));
699
700 /* Primary and cursor planes */
701 err = vkms_config_plane_attach_crtc(cursor_cfg, crtc_cfg);
702 KUNIT_EXPECT_EQ(test, err, 0);
703 KUNIT_EXPECT_PTR_EQ(test,
704 vkms_config_crtc_primary_plane(config, crtc_cfg),
705 primary_cfg);
706 KUNIT_EXPECT_PTR_EQ(test,
707 vkms_config_crtc_cursor_plane(config, crtc_cfg),
708 cursor_cfg);
709
710 /* Detach primary and destroy cursor plane */
711 vkms_config_plane_detach_crtc(overlay_cfg, crtc_cfg);
712 vkms_config_plane_detach_crtc(primary_cfg, crtc_cfg);
713 vkms_config_destroy_plane(cursor_cfg);
714 KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg));
715 KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg));
716
717 vkms_config_destroy(config);
718 }
719
vkms_config_test_plane_get_possible_crtcs(struct kunit * test)720 static void vkms_config_test_plane_get_possible_crtcs(struct kunit *test)
721 {
722 struct vkms_config *config;
723 struct vkms_config_plane *plane_cfg1, *plane_cfg2;
724 struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
725 struct vkms_config_crtc *possible_crtc;
726 unsigned long idx = 0;
727 int n_crtcs = 0;
728 int err;
729
730 config = vkms_config_create("test");
731 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
732
733 plane_cfg1 = vkms_config_create_plane(config);
734 plane_cfg2 = vkms_config_create_plane(config);
735 crtc_cfg1 = vkms_config_create_crtc(config);
736 crtc_cfg2 = vkms_config_create_crtc(config);
737
738 /* No possible CRTCs */
739 vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc)
740 KUNIT_FAIL(test, "Unexpected possible CRTC");
741
742 vkms_config_plane_for_each_possible_crtc(plane_cfg2, idx, possible_crtc)
743 KUNIT_FAIL(test, "Unexpected possible CRTC");
744
745 /* Plane 1 attached to CRTC 1 and 2 */
746 err = vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg1);
747 KUNIT_EXPECT_EQ(test, err, 0);
748 err = vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg2);
749 KUNIT_EXPECT_EQ(test, err, 0);
750
751 vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc) {
752 n_crtcs++;
753 if (possible_crtc != crtc_cfg1 && possible_crtc != crtc_cfg2)
754 KUNIT_FAIL(test, "Unexpected possible CRTC");
755 }
756 KUNIT_ASSERT_EQ(test, n_crtcs, 2);
757 n_crtcs = 0;
758
759 vkms_config_plane_for_each_possible_crtc(plane_cfg2, idx, possible_crtc)
760 KUNIT_FAIL(test, "Unexpected possible CRTC");
761
762 /* Plane 1 attached to CRTC 1 and plane 2 to CRTC 2 */
763 vkms_config_plane_detach_crtc(plane_cfg1, crtc_cfg2);
764 vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc) {
765 n_crtcs++;
766 if (possible_crtc != crtc_cfg1)
767 KUNIT_FAIL(test, "Unexpected possible CRTC");
768 }
769 KUNIT_ASSERT_EQ(test, n_crtcs, 1);
770 n_crtcs = 0;
771
772 err = vkms_config_plane_attach_crtc(plane_cfg2, crtc_cfg2);
773 KUNIT_EXPECT_EQ(test, err, 0);
774 vkms_config_plane_for_each_possible_crtc(plane_cfg2, idx, possible_crtc) {
775 n_crtcs++;
776 if (possible_crtc != crtc_cfg2)
777 KUNIT_FAIL(test, "Unexpected possible CRTC");
778 }
779 KUNIT_ASSERT_EQ(test, n_crtcs, 1);
780
781 vkms_config_destroy(config);
782 }
783
vkms_config_test_encoder_get_possible_crtcs(struct kunit * test)784 static void vkms_config_test_encoder_get_possible_crtcs(struct kunit *test)
785 {
786 struct vkms_config *config;
787 struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2;
788 struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
789 struct vkms_config_crtc *possible_crtc;
790 unsigned long idx = 0;
791 int n_crtcs = 0;
792 int err;
793
794 config = vkms_config_create("test");
795 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
796
797 encoder_cfg1 = vkms_config_create_encoder(config);
798 encoder_cfg2 = vkms_config_create_encoder(config);
799 crtc_cfg1 = vkms_config_create_crtc(config);
800 crtc_cfg2 = vkms_config_create_crtc(config);
801
802 /* No possible CRTCs */
803 vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_crtc)
804 KUNIT_FAIL(test, "Unexpected possible CRTC");
805
806 vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_crtc)
807 KUNIT_FAIL(test, "Unexpected possible CRTC");
808
809 /* Encoder 1 attached to CRTC 1 and 2 */
810 err = vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg1);
811 KUNIT_EXPECT_EQ(test, err, 0);
812 err = vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg2);
813 KUNIT_EXPECT_EQ(test, err, 0);
814
815 vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_crtc) {
816 n_crtcs++;
817 if (possible_crtc != crtc_cfg1 && possible_crtc != crtc_cfg2)
818 KUNIT_FAIL(test, "Unexpected possible CRTC");
819 }
820 KUNIT_ASSERT_EQ(test, n_crtcs, 2);
821 n_crtcs = 0;
822
823 vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_crtc)
824 KUNIT_FAIL(test, "Unexpected possible CRTC");
825
826 /* Encoder 1 attached to CRTC 1 and encoder 2 to CRTC 2 */
827 vkms_config_encoder_detach_crtc(encoder_cfg1, crtc_cfg2);
828 vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_crtc) {
829 n_crtcs++;
830 if (possible_crtc != crtc_cfg1)
831 KUNIT_FAIL(test, "Unexpected possible CRTC");
832 }
833 KUNIT_ASSERT_EQ(test, n_crtcs, 1);
834 n_crtcs = 0;
835
836 err = vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg2);
837 KUNIT_EXPECT_EQ(test, err, 0);
838 vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_crtc) {
839 n_crtcs++;
840 if (possible_crtc != crtc_cfg2)
841 KUNIT_FAIL(test, "Unexpected possible CRTC");
842 }
843 KUNIT_ASSERT_EQ(test, n_crtcs, 1);
844
845 vkms_config_destroy(config);
846 }
847
vkms_config_test_connector_get_possible_encoders(struct kunit * test)848 static void vkms_config_test_connector_get_possible_encoders(struct kunit *test)
849 {
850 struct vkms_config *config;
851 struct vkms_config_connector *connector_cfg1, *connector_cfg2;
852 struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2;
853 struct vkms_config_encoder *possible_encoder;
854 unsigned long idx = 0;
855 int n_encoders = 0;
856 int err;
857
858 config = vkms_config_create("test");
859 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
860
861 connector_cfg1 = vkms_config_create_connector(config);
862 connector_cfg2 = vkms_config_create_connector(config);
863 encoder_cfg1 = vkms_config_create_encoder(config);
864 encoder_cfg2 = vkms_config_create_encoder(config);
865
866 /* No possible encoders */
867 vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx,
868 possible_encoder)
869 KUNIT_FAIL(test, "Unexpected possible encoder");
870
871 vkms_config_connector_for_each_possible_encoder(connector_cfg2, idx,
872 possible_encoder)
873 KUNIT_FAIL(test, "Unexpected possible encoder");
874
875 /* Connector 1 attached to encoders 1 and 2 */
876 err = vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg1);
877 KUNIT_EXPECT_EQ(test, err, 0);
878 err = vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg2);
879 KUNIT_EXPECT_EQ(test, err, 0);
880
881 vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx,
882 possible_encoder) {
883 n_encoders++;
884 if (possible_encoder != encoder_cfg1 &&
885 possible_encoder != encoder_cfg2)
886 KUNIT_FAIL(test, "Unexpected possible encoder");
887 }
888 KUNIT_ASSERT_EQ(test, n_encoders, 2);
889 n_encoders = 0;
890
891 vkms_config_connector_for_each_possible_encoder(connector_cfg2, idx,
892 possible_encoder)
893 KUNIT_FAIL(test, "Unexpected possible encoder");
894
895 /* Connector 1 attached to encoder 1 and connector 2 to encoder 2 */
896 vkms_config_connector_detach_encoder(connector_cfg1, encoder_cfg2);
897 vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx,
898 possible_encoder) {
899 n_encoders++;
900 if (possible_encoder != encoder_cfg1)
901 KUNIT_FAIL(test, "Unexpected possible encoder");
902 }
903 KUNIT_ASSERT_EQ(test, n_encoders, 1);
904 n_encoders = 0;
905
906 err = vkms_config_connector_attach_encoder(connector_cfg2, encoder_cfg2);
907 KUNIT_EXPECT_EQ(test, err, 0);
908 vkms_config_connector_for_each_possible_encoder(connector_cfg2, idx,
909 possible_encoder) {
910 n_encoders++;
911 if (possible_encoder != encoder_cfg2)
912 KUNIT_FAIL(test, "Unexpected possible encoder");
913 }
914 KUNIT_ASSERT_EQ(test, n_encoders, 1);
915
916 vkms_config_destroy(config);
917 }
918
919 static struct kunit_case vkms_config_test_cases[] = {
920 KUNIT_CASE(vkms_config_test_empty_config),
921 KUNIT_CASE_PARAM(vkms_config_test_default_config,
922 default_config_gen_params),
923 KUNIT_CASE(vkms_config_test_get_planes),
924 KUNIT_CASE(vkms_config_test_get_crtcs),
925 KUNIT_CASE(vkms_config_test_get_encoders),
926 KUNIT_CASE(vkms_config_test_get_connectors),
927 KUNIT_CASE(vkms_config_test_invalid_plane_number),
928 KUNIT_CASE(vkms_config_test_valid_plane_type),
929 KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs),
930 KUNIT_CASE(vkms_config_test_invalid_crtc_number),
931 KUNIT_CASE(vkms_config_test_invalid_encoder_number),
932 KUNIT_CASE(vkms_config_test_valid_encoder_possible_crtcs),
933 KUNIT_CASE(vkms_config_test_invalid_connector_number),
934 KUNIT_CASE(vkms_config_test_valid_connector_possible_encoders),
935 KUNIT_CASE(vkms_config_test_attach_different_configs),
936 KUNIT_CASE(vkms_config_test_plane_attach_crtc),
937 KUNIT_CASE(vkms_config_test_plane_get_possible_crtcs),
938 KUNIT_CASE(vkms_config_test_encoder_get_possible_crtcs),
939 KUNIT_CASE(vkms_config_test_connector_get_possible_encoders),
940 {}
941 };
942
943 static struct kunit_suite vkms_config_test_suite = {
944 .name = "vkms-config",
945 .test_cases = vkms_config_test_cases,
946 };
947
948 kunit_test_suite(vkms_config_test_suite);
949
950 MODULE_LICENSE("GPL");
951 MODULE_DESCRIPTION("Kunit test for vkms config utility");
952