xref: /linux/drivers/gpu/drm/vkms/tests/vkms_config_test.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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