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