Files
linux/drivers/gpu/drm/vkms/tests/vkms_config_test.c
José Expósito b8776fc9b2 drm/vkms: Allow to attach encoders and CRTCs
Add a list of possible CRTCs to the encoder configuration and helpers to
attach and detach them.

Now that the default configuration has its encoder and CRTC correctly
attached, configure the output following the configuration.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Co-developed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250218101214.5790-13-jose.exposito89@gmail.com
Signed-off-by: Maxime Ripard <mripard@kernel.org>
2025-03-07 10:58:27 +01:00

755 lines
23 KiB
C

// SPDX-License-Identifier: GPL-2.0+
#include <kunit/test.h>
#include "../vkms_config.h"
MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static size_t vkms_config_get_num_planes(struct vkms_config *config)
{
struct vkms_config_plane *plane_cfg;
size_t count = 0;
vkms_config_for_each_plane(config, plane_cfg)
count++;
return count;
}
static size_t vkms_config_get_num_encoders(struct vkms_config *config)
{
struct vkms_config_encoder *encoder_cfg;
size_t count = 0;
vkms_config_for_each_encoder(config, encoder_cfg)
count++;
return count;
}
static struct vkms_config_plane *get_first_plane(struct vkms_config *config)
{
struct vkms_config_plane *plane_cfg;
vkms_config_for_each_plane(config, plane_cfg)
return plane_cfg;
return NULL;
}
static struct vkms_config_crtc *get_first_crtc(struct vkms_config *config)
{
struct vkms_config_crtc *crtc_cfg;
vkms_config_for_each_crtc(config, crtc_cfg)
return crtc_cfg;
return NULL;
}
static struct vkms_config_encoder *get_first_encoder(struct vkms_config *config)
{
struct vkms_config_encoder *encoder_cfg;
vkms_config_for_each_encoder(config, encoder_cfg)
return encoder_cfg;
return NULL;
}
struct default_config_case {
bool enable_cursor;
bool enable_writeback;
bool enable_overlay;
};
static void vkms_config_test_empty_config(struct kunit *test)
{
struct vkms_config *config;
const char *dev_name = "test";
config = vkms_config_create(dev_name);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
/* The dev_name string and the config have different lifetimes */
dev_name = NULL;
KUNIT_EXPECT_STREQ(test, vkms_config_get_device_name(config), "test");
KUNIT_EXPECT_EQ(test, vkms_config_get_num_planes(config), 0);
KUNIT_EXPECT_EQ(test, vkms_config_get_num_crtcs(config), 0);
KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 0);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
vkms_config_destroy(config);
}
static struct default_config_case default_config_cases[] = {
{ false, false, false },
{ true, false, false },
{ true, true, false },
{ true, false, true },
{ false, true, false },
{ false, true, true },
{ false, false, true },
{ true, true, true },
};
KUNIT_ARRAY_PARAM(default_config, default_config_cases, NULL);
static void vkms_config_test_default_config(struct kunit *test)
{
const struct default_config_case *params = test->param_value;
struct vkms_config *config;
struct vkms_config_plane *plane_cfg;
struct vkms_config_crtc *crtc_cfg;
int n_primaries = 0;
int n_cursors = 0;
int n_overlays = 0;
config = vkms_config_default_create(params->enable_cursor,
params->enable_writeback,
params->enable_overlay);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
/* Planes */
vkms_config_for_each_plane(config, plane_cfg) {
switch (vkms_config_plane_get_type(plane_cfg)) {
case DRM_PLANE_TYPE_PRIMARY:
n_primaries++;
break;
case DRM_PLANE_TYPE_CURSOR:
n_cursors++;
break;
case DRM_PLANE_TYPE_OVERLAY:
n_overlays++;
break;
default:
KUNIT_FAIL_AND_ABORT(test, "Unknown plane type");
}
}
KUNIT_EXPECT_EQ(test, n_primaries, 1);
KUNIT_EXPECT_EQ(test, n_cursors, params->enable_cursor ? 1 : 0);
KUNIT_EXPECT_EQ(test, n_overlays, params->enable_overlay ? 8 : 0);
/* CRTCs */
KUNIT_EXPECT_EQ(test, vkms_config_get_num_crtcs(config), 1);
crtc_cfg = get_first_crtc(config);
KUNIT_EXPECT_EQ(test, vkms_config_crtc_get_writeback(crtc_cfg),
params->enable_writeback);
vkms_config_for_each_plane(config, plane_cfg) {
struct vkms_config_crtc *possible_crtc;
int n_possible_crtcs = 0;
unsigned long idx = 0;
vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) {
KUNIT_EXPECT_PTR_EQ(test, crtc_cfg, possible_crtc);
n_possible_crtcs++;
}
KUNIT_EXPECT_EQ(test, n_possible_crtcs, 1);
}
/* Encoders */
KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 1);
KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
vkms_config_destroy(config);
}
static void vkms_config_test_get_planes(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_plane *plane_cfg;
struct vkms_config_plane *plane_cfg1, *plane_cfg2;
int n_planes = 0;
config = vkms_config_create("test");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
vkms_config_for_each_plane(config, plane_cfg)
n_planes++;
KUNIT_ASSERT_EQ(test, n_planes, 0);
plane_cfg1 = vkms_config_create_plane(config);
vkms_config_for_each_plane(config, plane_cfg) {
n_planes++;
if (plane_cfg != plane_cfg1)
KUNIT_FAIL(test, "Unexpected plane");
}
KUNIT_ASSERT_EQ(test, n_planes, 1);
n_planes = 0;
plane_cfg2 = vkms_config_create_plane(config);
vkms_config_for_each_plane(config, plane_cfg) {
n_planes++;
if (plane_cfg != plane_cfg1 && plane_cfg != plane_cfg2)
KUNIT_FAIL(test, "Unexpected plane");
}
KUNIT_ASSERT_EQ(test, n_planes, 2);
n_planes = 0;
vkms_config_destroy_plane(plane_cfg1);
vkms_config_for_each_plane(config, plane_cfg) {
n_planes++;
if (plane_cfg != plane_cfg2)
KUNIT_FAIL(test, "Unexpected plane");
}
KUNIT_ASSERT_EQ(test, n_planes, 1);
vkms_config_destroy(config);
}
static void vkms_config_test_get_crtcs(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_crtc *crtc_cfg;
struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
config = vkms_config_create("test");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 0);
vkms_config_for_each_crtc(config, crtc_cfg)
KUNIT_FAIL(test, "Unexpected CRTC");
crtc_cfg1 = vkms_config_create_crtc(config);
KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 1);
vkms_config_for_each_crtc(config, crtc_cfg) {
if (crtc_cfg != crtc_cfg1)
KUNIT_FAIL(test, "Unexpected CRTC");
}
crtc_cfg2 = vkms_config_create_crtc(config);
KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 2);
vkms_config_for_each_crtc(config, crtc_cfg) {
if (crtc_cfg != crtc_cfg1 && crtc_cfg != crtc_cfg2)
KUNIT_FAIL(test, "Unexpected CRTC");
}
vkms_config_destroy_crtc(config, crtc_cfg2);
KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 1);
vkms_config_for_each_crtc(config, crtc_cfg) {
if (crtc_cfg != crtc_cfg1)
KUNIT_FAIL(test, "Unexpected CRTC");
}
vkms_config_destroy(config);
}
static void vkms_config_test_get_encoders(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_encoder *encoder_cfg;
struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2;
int n_encoders = 0;
config = vkms_config_create("test");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
vkms_config_for_each_encoder(config, encoder_cfg)
n_encoders++;
KUNIT_ASSERT_EQ(test, n_encoders, 0);
encoder_cfg1 = vkms_config_create_encoder(config);
vkms_config_for_each_encoder(config, encoder_cfg) {
n_encoders++;
if (encoder_cfg != encoder_cfg1)
KUNIT_FAIL(test, "Unexpected encoder");
}
KUNIT_ASSERT_EQ(test, n_encoders, 1);
n_encoders = 0;
encoder_cfg2 = vkms_config_create_encoder(config);
vkms_config_for_each_encoder(config, encoder_cfg) {
n_encoders++;
if (encoder_cfg != encoder_cfg1 && encoder_cfg != encoder_cfg2)
KUNIT_FAIL(test, "Unexpected encoder");
}
KUNIT_ASSERT_EQ(test, n_encoders, 2);
n_encoders = 0;
vkms_config_destroy_encoder(config, encoder_cfg2);
vkms_config_for_each_encoder(config, encoder_cfg) {
n_encoders++;
if (encoder_cfg != encoder_cfg1)
KUNIT_FAIL(test, "Unexpected encoder");
}
KUNIT_ASSERT_EQ(test, n_encoders, 1);
n_encoders = 0;
vkms_config_destroy(config);
}
static void vkms_config_test_invalid_plane_number(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_plane *plane_cfg;
int n;
config = vkms_config_default_create(false, false, false);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
/* Invalid: No planes */
plane_cfg = get_first_plane(config);
vkms_config_destroy_plane(plane_cfg);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
/* Invalid: Too many planes */
for (n = 0; n <= 32; n++)
vkms_config_create_plane(config);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
vkms_config_destroy(config);
}
static void vkms_config_test_valid_plane_type(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_plane *plane_cfg;
struct vkms_config_crtc *crtc_cfg;
struct vkms_config_encoder *encoder_cfg;
int err;
config = vkms_config_default_create(false, false, false);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
plane_cfg = get_first_plane(config);
vkms_config_destroy_plane(plane_cfg);
crtc_cfg = get_first_crtc(config);
/* Invalid: No primary plane */
plane_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
/* Invalid: Multiple primary planes */
plane_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
plane_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
/* Valid: One primary plane */
vkms_config_destroy_plane(plane_cfg);
KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
/* Invalid: Multiple cursor planes */
plane_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR);
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
plane_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR);
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
/* Valid: One primary and one cursor plane */
vkms_config_destroy_plane(plane_cfg);
KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
/* Invalid: Second CRTC without primary plane */
crtc_cfg = vkms_config_create_crtc(config);
encoder_cfg = vkms_config_create_encoder(config);
err = vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
/* Valid: Second CRTC with a primary plane */
plane_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
vkms_config_destroy(config);
}
static void vkms_config_test_valid_plane_possible_crtcs(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_plane *plane_cfg;
struct vkms_config_crtc *crtc_cfg;
config = vkms_config_default_create(false, false, false);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
plane_cfg = get_first_plane(config);
crtc_cfg = get_first_crtc(config);
/* Invalid: Primary plane without a possible CRTC */
vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
vkms_config_destroy(config);
}
static void vkms_config_test_invalid_crtc_number(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_crtc *crtc_cfg;
int n;
config = vkms_config_default_create(false, false, false);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
/* Invalid: No CRTCs */
crtc_cfg = get_first_crtc(config);
vkms_config_destroy_crtc(config, crtc_cfg);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
/* Invalid: Too many CRTCs */
for (n = 0; n <= 32; n++)
vkms_config_create_crtc(config);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
vkms_config_destroy(config);
}
static void vkms_config_test_invalid_encoder_number(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_encoder *encoder_cfg;
int n;
config = vkms_config_default_create(false, false, false);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
/* Invalid: No encoders */
encoder_cfg = get_first_encoder(config);
vkms_config_destroy_encoder(config, encoder_cfg);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
/* Invalid: Too many encoders */
for (n = 0; n <= 32; n++)
vkms_config_create_encoder(config);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
vkms_config_destroy(config);
}
static void vkms_config_test_valid_encoder_possible_crtcs(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_plane *plane_cfg;
struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
struct vkms_config_encoder *encoder_cfg;
int err;
config = vkms_config_default_create(false, false, false);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
crtc_cfg1 = get_first_crtc(config);
/* Invalid: Encoder without a possible CRTC */
encoder_cfg = vkms_config_create_encoder(config);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
/* Valid: Second CRTC with shared encoder */
crtc_cfg2 = vkms_config_create_crtc(config);
plane_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg2);
KUNIT_EXPECT_EQ(test, err, 0);
err = vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg1);
KUNIT_EXPECT_EQ(test, err, 0);
err = vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg2);
KUNIT_EXPECT_EQ(test, err, 0);
KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
/* Invalid: Second CRTC without encoders */
vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg2);
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
/* Valid: First CRTC with 2 possible encoder */
vkms_config_destroy_plane(plane_cfg);
vkms_config_destroy_crtc(config, crtc_cfg2);
KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
vkms_config_destroy(config);
}
static void vkms_config_test_attach_different_configs(struct kunit *test)
{
struct vkms_config *config1, *config2;
struct vkms_config_plane *plane_cfg1, *plane_cfg2;
struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2;
int err;
config1 = vkms_config_create("test1");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config1);
config2 = vkms_config_create("test2");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config2);
plane_cfg1 = vkms_config_create_plane(config1);
crtc_cfg1 = vkms_config_create_crtc(config1);
encoder_cfg1 = vkms_config_create_encoder(config1);
plane_cfg2 = vkms_config_create_plane(config2);
crtc_cfg2 = vkms_config_create_crtc(config2);
encoder_cfg2 = vkms_config_create_encoder(config2);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg1);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg2);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg1);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg1);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg2);
err = vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg2);
KUNIT_EXPECT_NE(test, err, 0);
err = vkms_config_plane_attach_crtc(plane_cfg2, crtc_cfg1);
KUNIT_EXPECT_NE(test, err, 0);
err = vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg2);
KUNIT_EXPECT_NE(test, err, 0);
err = vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg1);
KUNIT_EXPECT_NE(test, err, 0);
vkms_config_destroy(config1);
vkms_config_destroy(config2);
}
static void vkms_config_test_plane_attach_crtc(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_plane *overlay_cfg;
struct vkms_config_plane *primary_cfg;
struct vkms_config_plane *cursor_cfg;
struct vkms_config_crtc *crtc_cfg;
int err;
config = vkms_config_create("test");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
overlay_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(overlay_cfg, DRM_PLANE_TYPE_OVERLAY);
primary_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(primary_cfg, DRM_PLANE_TYPE_PRIMARY);
cursor_cfg = vkms_config_create_plane(config);
vkms_config_plane_set_type(cursor_cfg, DRM_PLANE_TYPE_CURSOR);
crtc_cfg = vkms_config_create_crtc(config);
/* No primary or cursor planes */
KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg));
KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg));
/* Overlay plane, but no primary or cursor planes */
err = vkms_config_plane_attach_crtc(overlay_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg));
KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg));
/* Primary plane, attaching it twice must fail */
err = vkms_config_plane_attach_crtc(primary_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
err = vkms_config_plane_attach_crtc(primary_cfg, crtc_cfg);
KUNIT_EXPECT_NE(test, err, 0);
KUNIT_EXPECT_PTR_EQ(test,
vkms_config_crtc_primary_plane(config, crtc_cfg),
primary_cfg);
KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg));
/* Primary and cursor planes */
err = vkms_config_plane_attach_crtc(cursor_cfg, crtc_cfg);
KUNIT_EXPECT_EQ(test, err, 0);
KUNIT_EXPECT_PTR_EQ(test,
vkms_config_crtc_primary_plane(config, crtc_cfg),
primary_cfg);
KUNIT_EXPECT_PTR_EQ(test,
vkms_config_crtc_cursor_plane(config, crtc_cfg),
cursor_cfg);
/* Detach primary and destroy cursor plane */
vkms_config_plane_detach_crtc(overlay_cfg, crtc_cfg);
vkms_config_plane_detach_crtc(primary_cfg, crtc_cfg);
vkms_config_destroy_plane(cursor_cfg);
KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg));
KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg));
vkms_config_destroy(config);
}
static void vkms_config_test_plane_get_possible_crtcs(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_plane *plane_cfg1, *plane_cfg2;
struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
struct vkms_config_crtc *possible_crtc;
unsigned long idx = 0;
int n_crtcs = 0;
int err;
config = vkms_config_create("test");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
plane_cfg1 = vkms_config_create_plane(config);
plane_cfg2 = vkms_config_create_plane(config);
crtc_cfg1 = vkms_config_create_crtc(config);
crtc_cfg2 = vkms_config_create_crtc(config);
/* No possible CRTCs */
vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc)
KUNIT_FAIL(test, "Unexpected possible CRTC");
vkms_config_plane_for_each_possible_crtc(plane_cfg2, idx, possible_crtc)
KUNIT_FAIL(test, "Unexpected possible CRTC");
/* Plane 1 attached to CRTC 1 and 2 */
err = vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg1);
KUNIT_EXPECT_EQ(test, err, 0);
err = vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg2);
KUNIT_EXPECT_EQ(test, err, 0);
vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc) {
n_crtcs++;
if (possible_crtc != crtc_cfg1 && possible_crtc != crtc_cfg2)
KUNIT_FAIL(test, "Unexpected possible CRTC");
}
KUNIT_ASSERT_EQ(test, n_crtcs, 2);
n_crtcs = 0;
vkms_config_plane_for_each_possible_crtc(plane_cfg2, idx, possible_crtc)
KUNIT_FAIL(test, "Unexpected possible CRTC");
/* Plane 1 attached to CRTC 1 and plane 2 to CRTC 2 */
vkms_config_plane_detach_crtc(plane_cfg1, crtc_cfg2);
vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc) {
n_crtcs++;
if (possible_crtc != crtc_cfg1)
KUNIT_FAIL(test, "Unexpected possible CRTC");
}
KUNIT_ASSERT_EQ(test, n_crtcs, 1);
n_crtcs = 0;
err = vkms_config_plane_attach_crtc(plane_cfg2, crtc_cfg2);
KUNIT_EXPECT_EQ(test, err, 0);
vkms_config_plane_for_each_possible_crtc(plane_cfg2, idx, possible_crtc) {
n_crtcs++;
if (possible_crtc != crtc_cfg2)
KUNIT_FAIL(test, "Unexpected possible CRTC");
}
KUNIT_ASSERT_EQ(test, n_crtcs, 1);
vkms_config_destroy(config);
}
static void vkms_config_test_encoder_get_possible_crtcs(struct kunit *test)
{
struct vkms_config *config;
struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2;
struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2;
struct vkms_config_crtc *possible_crtc;
unsigned long idx = 0;
int n_crtcs = 0;
int err;
config = vkms_config_create("test");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
encoder_cfg1 = vkms_config_create_encoder(config);
encoder_cfg2 = vkms_config_create_encoder(config);
crtc_cfg1 = vkms_config_create_crtc(config);
crtc_cfg2 = vkms_config_create_crtc(config);
/* No possible CRTCs */
vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_crtc)
KUNIT_FAIL(test, "Unexpected possible CRTC");
vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_crtc)
KUNIT_FAIL(test, "Unexpected possible CRTC");
/* Encoder 1 attached to CRTC 1 and 2 */
err = vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg1);
KUNIT_EXPECT_EQ(test, err, 0);
err = vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg2);
KUNIT_EXPECT_EQ(test, err, 0);
vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_crtc) {
n_crtcs++;
if (possible_crtc != crtc_cfg1 && possible_crtc != crtc_cfg2)
KUNIT_FAIL(test, "Unexpected possible CRTC");
}
KUNIT_ASSERT_EQ(test, n_crtcs, 2);
n_crtcs = 0;
vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_crtc)
KUNIT_FAIL(test, "Unexpected possible CRTC");
/* Encoder 1 attached to CRTC 1 and encoder 2 to CRTC 2 */
vkms_config_encoder_detach_crtc(encoder_cfg1, crtc_cfg2);
vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_crtc) {
n_crtcs++;
if (possible_crtc != crtc_cfg1)
KUNIT_FAIL(test, "Unexpected possible CRTC");
}
KUNIT_ASSERT_EQ(test, n_crtcs, 1);
n_crtcs = 0;
err = vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg2);
KUNIT_EXPECT_EQ(test, err, 0);
vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_crtc) {
n_crtcs++;
if (possible_crtc != crtc_cfg2)
KUNIT_FAIL(test, "Unexpected possible CRTC");
}
KUNIT_ASSERT_EQ(test, n_crtcs, 1);
vkms_config_destroy(config);
}
static struct kunit_case vkms_config_test_cases[] = {
KUNIT_CASE(vkms_config_test_empty_config),
KUNIT_CASE_PARAM(vkms_config_test_default_config,
default_config_gen_params),
KUNIT_CASE(vkms_config_test_get_planes),
KUNIT_CASE(vkms_config_test_get_crtcs),
KUNIT_CASE(vkms_config_test_get_encoders),
KUNIT_CASE(vkms_config_test_invalid_plane_number),
KUNIT_CASE(vkms_config_test_valid_plane_type),
KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs),
KUNIT_CASE(vkms_config_test_invalid_crtc_number),
KUNIT_CASE(vkms_config_test_invalid_encoder_number),
KUNIT_CASE(vkms_config_test_valid_encoder_possible_crtcs),
KUNIT_CASE(vkms_config_test_attach_different_configs),
KUNIT_CASE(vkms_config_test_plane_attach_crtc),
KUNIT_CASE(vkms_config_test_plane_get_possible_crtcs),
KUNIT_CASE(vkms_config_test_encoder_get_possible_crtcs),
{}
};
static struct kunit_suite vkms_config_test_suite = {
.name = "vkms-config",
.test_cases = vkms_config_test_cases,
};
kunit_test_suite(vkms_config_test_suite);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Kunit test for vkms config utility");