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