531 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Test cases for the drm_rect functions4 *5 * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>6 */7 8#include <kunit/test.h>9 10#include <drm/drm_rect.h>11#include <drm/drm_mode.h>12 13#include <linux/string_helpers.h>14#include <linux/errno.h>15 16static void drm_rect_compare(struct kunit *test, const struct drm_rect *r,17 const struct drm_rect *expected)18{19 KUNIT_EXPECT_EQ(test, r->x1, expected->x1);20 KUNIT_EXPECT_EQ(test, r->y1, expected->y1);21 KUNIT_EXPECT_EQ(test, drm_rect_width(r), drm_rect_width(expected));22 KUNIT_EXPECT_EQ(test, drm_rect_height(r), drm_rect_height(expected));23}24 25static void drm_test_rect_clip_scaled_div_by_zero(struct kunit *test)26{27 struct drm_rect src, dst, clip;28 bool visible;29 30 /*31 * Make sure we don't divide by zero when dst32 * width/height is zero and dst and clip do not intersect.33 */34 drm_rect_init(&src, 0, 0, 0, 0);35 drm_rect_init(&dst, 0, 0, 0, 0);36 drm_rect_init(&clip, 1, 1, 1, 1);37 visible = drm_rect_clip_scaled(&src, &dst, &clip);38 39 KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n");40 KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");41 42 drm_rect_init(&src, 0, 0, 0, 0);43 drm_rect_init(&dst, 3, 3, 0, 0);44 drm_rect_init(&clip, 1, 1, 1, 1);45 visible = drm_rect_clip_scaled(&src, &dst, &clip);46 47 KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n");48 KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");49}50 51static void drm_test_rect_clip_scaled_not_clipped(struct kunit *test)52{53 struct drm_rect src, dst, clip;54 bool visible;55 56 /* 1:1 scaling */57 drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);58 drm_rect_init(&dst, 0, 0, 1, 1);59 drm_rect_init(&clip, 0, 0, 1, 1);60 61 visible = drm_rect_clip_scaled(&src, &dst, &clip);62 63 KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||64 src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");65 KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||66 dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");67 KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");68 KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");69 70 /* 2:1 scaling */71 drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);72 drm_rect_init(&dst, 0, 0, 1, 1);73 drm_rect_init(&clip, 0, 0, 1, 1);74 75 visible = drm_rect_clip_scaled(&src, &dst, &clip);76 77 KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 ||78 src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n");79 KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||80 dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");81 KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");82 KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");83 84 /* 1:2 scaling */85 drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);86 drm_rect_init(&dst, 0, 0, 2, 2);87 drm_rect_init(&clip, 0, 0, 2, 2);88 89 visible = drm_rect_clip_scaled(&src, &dst, &clip);90 91 KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||92 src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");93 KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 ||94 dst.y1 != 0 || dst.y2 != 2, "Destination badly clipped\n");95 KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");96 KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");97}98 99static void drm_test_rect_clip_scaled_clipped(struct kunit *test)100{101 struct drm_rect src, dst, clip;102 bool visible;103 104 /* 1:1 scaling top/left clip */105 drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);106 drm_rect_init(&dst, 0, 0, 2, 2);107 drm_rect_init(&clip, 0, 0, 1, 1);108 109 visible = drm_rect_clip_scaled(&src, &dst, &clip);110 111 KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||112 src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");113 KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||114 dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");115 KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");116 KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");117 118 /* 1:1 scaling bottom/right clip */119 drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);120 drm_rect_init(&dst, 0, 0, 2, 2);121 drm_rect_init(&clip, 1, 1, 1, 1);122 123 visible = drm_rect_clip_scaled(&src, &dst, &clip);124 125 KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 ||126 src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n");127 KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 ||128 dst.y2 != 2, "Destination badly clipped\n");129 KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");130 KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");131 132 /* 2:1 scaling top/left clip */133 drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);134 drm_rect_init(&dst, 0, 0, 2, 2);135 drm_rect_init(&clip, 0, 0, 1, 1);136 137 visible = drm_rect_clip_scaled(&src, &dst, &clip);138 139 KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 ||140 src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n");141 KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || dst.y1 != 0 ||142 dst.y2 != 1, "Destination badly clipped\n");143 KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");144 KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");145 146 /* 2:1 scaling bottom/right clip */147 drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);148 drm_rect_init(&dst, 0, 0, 2, 2);149 drm_rect_init(&clip, 1, 1, 1, 1);150 151 visible = drm_rect_clip_scaled(&src, &dst, &clip);152 153 KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 2 << 16 || src.x2 != 4 << 16 ||154 src.y1 != 2 << 16 || src.y2 != 4 << 16, "Source badly clipped\n");155 KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 ||156 dst.y2 != 2, "Destination badly clipped\n");157 KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");158 KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");159 160 /* 1:2 scaling top/left clip */161 drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);162 drm_rect_init(&dst, 0, 0, 4, 4);163 drm_rect_init(&clip, 0, 0, 2, 2);164 165 visible = drm_rect_clip_scaled(&src, &dst, &clip);166 167 KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||168 src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");169 KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || dst.y1 != 0 ||170 dst.y2 != 2, "Destination badly clipped\n");171 KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");172 KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");173 174 /* 1:2 scaling bottom/right clip */175 drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);176 drm_rect_init(&dst, 0, 0, 4, 4);177 drm_rect_init(&clip, 2, 2, 2, 2);178 179 visible = drm_rect_clip_scaled(&src, &dst, &clip);180 181 KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 ||182 src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n");183 KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 2 || dst.x2 != 4 || dst.y1 != 2 ||184 dst.y2 != 4, "Destination badly clipped\n");185 KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");186 KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");187}188 189static void drm_test_rect_clip_scaled_signed_vs_unsigned(struct kunit *test)190{191 struct drm_rect src, dst, clip;192 bool visible;193 194 /*195 * 'clip.x2 - dst.x1 >= dst width' could result a negative196 * src rectangle width which is no longer expected by the197 * code as it's using unsigned types. This could lead to198 * the clipped source rectangle appering visible when it199 * should have been fully clipped. Make sure both rectangles200 * end up invisible.201 */202 drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX);203 drm_rect_init(&dst, 0, 0, 2, 2);204 drm_rect_init(&clip, 3, 3, 1, 1);205 206 visible = drm_rect_clip_scaled(&src, &dst, &clip);207 208 KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination should not be visible\n");209 KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");210}211 212struct drm_rect_intersect_case {213 const char *description;214 struct drm_rect r1, r2;215 bool should_be_visible;216 struct drm_rect expected_intersection;217};218 219static const struct drm_rect_intersect_case drm_rect_intersect_cases[] = {220 {221 .description = "top-left x bottom-right",222 .r1 = DRM_RECT_INIT(1, 1, 2, 2),223 .r2 = DRM_RECT_INIT(0, 0, 2, 2),224 .should_be_visible = true,225 .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),226 },227 {228 .description = "top-right x bottom-left",229 .r1 = DRM_RECT_INIT(0, 0, 2, 2),230 .r2 = DRM_RECT_INIT(1, -1, 2, 2),231 .should_be_visible = true,232 .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),233 },234 {235 .description = "bottom-left x top-right",236 .r1 = DRM_RECT_INIT(1, -1, 2, 2),237 .r2 = DRM_RECT_INIT(0, 0, 2, 2),238 .should_be_visible = true,239 .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),240 },241 {242 .description = "bottom-right x top-left",243 .r1 = DRM_RECT_INIT(0, 0, 2, 2),244 .r2 = DRM_RECT_INIT(1, 1, 2, 2),245 .should_be_visible = true,246 .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),247 },248 {249 .description = "right x left",250 .r1 = DRM_RECT_INIT(0, 0, 2, 1),251 .r2 = DRM_RECT_INIT(1, 0, 3, 1),252 .should_be_visible = true,253 .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),254 },255 {256 .description = "left x right",257 .r1 = DRM_RECT_INIT(1, 0, 3, 1),258 .r2 = DRM_RECT_INIT(0, 0, 2, 1),259 .should_be_visible = true,260 .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),261 },262 {263 .description = "up x bottom",264 .r1 = DRM_RECT_INIT(0, 0, 1, 2),265 .r2 = DRM_RECT_INIT(0, -1, 1, 3),266 .should_be_visible = true,267 .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2),268 },269 {270 .description = "bottom x up",271 .r1 = DRM_RECT_INIT(0, -1, 1, 3),272 .r2 = DRM_RECT_INIT(0, 0, 1, 2),273 .should_be_visible = true,274 .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2),275 },276 {277 .description = "touching corner",278 .r1 = DRM_RECT_INIT(0, 0, 1, 1),279 .r2 = DRM_RECT_INIT(1, 1, 2, 2),280 .should_be_visible = false,281 .expected_intersection = DRM_RECT_INIT(1, 1, 0, 0),282 },283 {284 .description = "touching side",285 .r1 = DRM_RECT_INIT(0, 0, 1, 1),286 .r2 = DRM_RECT_INIT(1, 0, 1, 1),287 .should_be_visible = false,288 .expected_intersection = DRM_RECT_INIT(1, 0, 0, 1),289 },290 {291 .description = "equal rects",292 .r1 = DRM_RECT_INIT(0, 0, 2, 2),293 .r2 = DRM_RECT_INIT(0, 0, 2, 2),294 .should_be_visible = true,295 .expected_intersection = DRM_RECT_INIT(0, 0, 2, 2),296 },297 {298 .description = "inside another",299 .r1 = DRM_RECT_INIT(0, 0, 2, 2),300 .r2 = DRM_RECT_INIT(1, 1, 1, 1),301 .should_be_visible = true,302 .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),303 },304 {305 .description = "far away",306 .r1 = DRM_RECT_INIT(0, 0, 1, 1),307 .r2 = DRM_RECT_INIT(3, 6, 1, 1),308 .should_be_visible = false,309 .expected_intersection = DRM_RECT_INIT(3, 6, -2, -5),310 },311 {312 .description = "points intersecting",313 .r1 = DRM_RECT_INIT(5, 10, 0, 0),314 .r2 = DRM_RECT_INIT(5, 10, 0, 0),315 .should_be_visible = false,316 .expected_intersection = DRM_RECT_INIT(5, 10, 0, 0),317 },318 {319 .description = "points not intersecting",320 .r1 = DRM_RECT_INIT(0, 0, 0, 0),321 .r2 = DRM_RECT_INIT(5, 10, 0, 0),322 .should_be_visible = false,323 .expected_intersection = DRM_RECT_INIT(5, 10, -5, -10),324 },325};326 327static void drm_rect_intersect_case_desc(const struct drm_rect_intersect_case *t, char *desc)328{329 snprintf(desc, KUNIT_PARAM_DESC_SIZE,330 "%s: " DRM_RECT_FMT " x " DRM_RECT_FMT,331 t->description, DRM_RECT_ARG(&t->r1), DRM_RECT_ARG(&t->r2));332}333 334KUNIT_ARRAY_PARAM(drm_rect_intersect, drm_rect_intersect_cases, drm_rect_intersect_case_desc);335 336static void drm_test_rect_intersect(struct kunit *test)337{338 const struct drm_rect_intersect_case *params = test->param_value;339 struct drm_rect r1_aux = params->r1;340 bool visible;341 342 visible = drm_rect_intersect(&r1_aux, ¶ms->r2);343 344 KUNIT_EXPECT_EQ(test, visible, params->should_be_visible);345 drm_rect_compare(test, &r1_aux, ¶ms->expected_intersection);346}347 348struct drm_rect_scale_case {349 const char *name;350 struct drm_rect src, dst;351 int min_range, max_range;352 int expected_scaling_factor;353};354 355static const struct drm_rect_scale_case drm_rect_scale_cases[] = {356 {357 .name = "normal use",358 .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16),359 .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),360 .min_range = 0, .max_range = INT_MAX,361 .expected_scaling_factor = 2,362 },363 {364 .name = "out of max range",365 .src = DRM_RECT_INIT(0, 0, 10 << 16, 10 << 16),366 .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),367 .min_range = 3, .max_range = 5,368 .expected_scaling_factor = -ERANGE,369 },370 {371 .name = "out of min range",372 .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16),373 .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),374 .min_range = 3, .max_range = 5,375 .expected_scaling_factor = -ERANGE,376 },377 {378 .name = "zero dst",379 .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16),380 .dst = DRM_RECT_INIT(0, 0, 0 << 16, 0 << 16),381 .min_range = 0, .max_range = INT_MAX,382 .expected_scaling_factor = 0,383 },384 {385 .name = "negative src",386 .src = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)),387 .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),388 .min_range = 0, .max_range = INT_MAX,389 .expected_scaling_factor = -EINVAL,390 },391 {392 .name = "negative dst",393 .src = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),394 .dst = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)),395 .min_range = 0, .max_range = INT_MAX,396 .expected_scaling_factor = -EINVAL,397 },398};399 400static void drm_rect_scale_case_desc(const struct drm_rect_scale_case *t, char *desc)401{402 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);403}404 405KUNIT_ARRAY_PARAM(drm_rect_scale, drm_rect_scale_cases, drm_rect_scale_case_desc);406 407static void drm_test_rect_calc_hscale(struct kunit *test)408{409 const struct drm_rect_scale_case *params = test->param_value;410 int scaling_factor;411 412 scaling_factor = drm_rect_calc_hscale(¶ms->src, ¶ms->dst,413 params->min_range, params->max_range);414 415 KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);416}417 418static void drm_test_rect_calc_vscale(struct kunit *test)419{420 const struct drm_rect_scale_case *params = test->param_value;421 int scaling_factor;422 423 scaling_factor = drm_rect_calc_vscale(¶ms->src, ¶ms->dst,424 params->min_range, params->max_range);425 426 KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);427}428 429struct drm_rect_rotate_case {430 const char *name;431 unsigned int rotation;432 struct drm_rect rect;433 int width, height;434 struct drm_rect expected;435};436 437static const struct drm_rect_rotate_case drm_rect_rotate_cases[] = {438 {439 .name = "reflect-x",440 .rotation = DRM_MODE_REFLECT_X,441 .rect = DRM_RECT_INIT(0, 0, 5, 5),442 .width = 5, .height = 10,443 .expected = DRM_RECT_INIT(0, 0, 5, 5),444 },445 {446 .name = "reflect-y",447 .rotation = DRM_MODE_REFLECT_Y,448 .rect = DRM_RECT_INIT(2, 0, 5, 5),449 .width = 5, .height = 10,450 .expected = DRM_RECT_INIT(2, 5, 5, 5),451 },452 {453 .name = "rotate-0",454 .rotation = DRM_MODE_ROTATE_0,455 .rect = DRM_RECT_INIT(0, 2, 5, 5),456 .width = 5, .height = 10,457 .expected = DRM_RECT_INIT(0, 2, 5, 5),458 },459 {460 .name = "rotate-90",461 .rotation = DRM_MODE_ROTATE_90,462 .rect = DRM_RECT_INIT(0, 0, 5, 10),463 .width = 5, .height = 10,464 .expected = DRM_RECT_INIT(0, 0, 10, 5),465 },466 {467 .name = "rotate-180",468 .rotation = DRM_MODE_ROTATE_180,469 .rect = DRM_RECT_INIT(11, 3, 5, 10),470 .width = 5, .height = 10,471 .expected = DRM_RECT_INIT(-11, -3, 5, 10),472 },473 {474 .name = "rotate-270",475 .rotation = DRM_MODE_ROTATE_270,476 .rect = DRM_RECT_INIT(6, 3, 5, 10),477 .width = 5, .height = 10,478 .expected = DRM_RECT_INIT(-3, 6, 10, 5),479 },480};481 482static void drm_rect_rotate_case_desc(const struct drm_rect_rotate_case *t, char *desc)483{484 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);485}486 487KUNIT_ARRAY_PARAM(drm_rect_rotate, drm_rect_rotate_cases, drm_rect_rotate_case_desc);488 489static void drm_test_rect_rotate(struct kunit *test)490{491 const struct drm_rect_rotate_case *params = test->param_value;492 struct drm_rect r = params->rect;493 494 drm_rect_rotate(&r, params->width, params->height, params->rotation);495 496 drm_rect_compare(test, &r, ¶ms->expected);497}498 499static void drm_test_rect_rotate_inv(struct kunit *test)500{501 const struct drm_rect_rotate_case *params = test->param_value;502 struct drm_rect r = params->expected;503 504 drm_rect_rotate_inv(&r, params->width, params->height, params->rotation);505 506 drm_rect_compare(test, &r, ¶ms->rect);507}508 509static struct kunit_case drm_rect_tests[] = {510 KUNIT_CASE(drm_test_rect_clip_scaled_div_by_zero),511 KUNIT_CASE(drm_test_rect_clip_scaled_not_clipped),512 KUNIT_CASE(drm_test_rect_clip_scaled_clipped),513 KUNIT_CASE(drm_test_rect_clip_scaled_signed_vs_unsigned),514 KUNIT_CASE_PARAM(drm_test_rect_intersect, drm_rect_intersect_gen_params),515 KUNIT_CASE_PARAM(drm_test_rect_calc_hscale, drm_rect_scale_gen_params),516 KUNIT_CASE_PARAM(drm_test_rect_calc_vscale, drm_rect_scale_gen_params),517 KUNIT_CASE_PARAM(drm_test_rect_rotate, drm_rect_rotate_gen_params),518 KUNIT_CASE_PARAM(drm_test_rect_rotate_inv, drm_rect_rotate_gen_params),519 { }520};521 522static struct kunit_suite drm_rect_test_suite = {523 .name = "drm_rect",524 .test_cases = drm_rect_tests,525};526 527kunit_test_suite(drm_rect_test_suite);528 529MODULE_DESCRIPTION("Test cases for the drm_rect functions");530MODULE_LICENSE("GPL");531