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