Some DRM helpers report the state of an object through a drm_printer, most notably to report which fields of two states differ when comparing them.
Tests exercising such code paths need to pass a drm_printer as well, and would rather have its output show up in the KTAP log of the test than anywhere else, so that a failure comes with the report that caused it. Add drm_kunit_helper_printer() that returns a drm_printer whose messages are logged through kunit_log() at the LOGLEVEL_* level requested by the caller. Signed-off-by: Maxime Ripard <[email protected]> --- drivers/gpu/drm/tests/drm_kunit_helpers.c | 78 +++++++++++++++++++++++++++++++ include/drm/drm_kunit_helpers.h | 4 ++ 2 files changed, 82 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index 63d024946500..fad911772ee5 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -9,4 +9,5 @@ #include <drm/drm_kunit_helpers.h> #include <drm/drm_managed.h> +#include <drm/drm_print.h> #include <kunit/device.h> @@ -19,4 +20,81 @@ #define KUNIT_DEVICE_NAME "drm-kunit-mock-device" +struct drm_printer_ctx { + struct drm_printer p; + int level; + struct kunit *test; +}; + +/* + * kunit_log() is a macro that only accepts a compile-time log level, + * so the level has to be dispatched to the matching kunit_log() call. + */ +static void drm_kunit_printf(struct drm_printer *p, struct va_format *vaf) +{ + struct drm_printer_ctx *ctx = p->arg; + + switch (ctx->level) { + case LOGLEVEL_EMERG: + kunit_log(KERN_EMERG, ctx->test, "%pV", vaf); + break; + case LOGLEVEL_ALERT: + kunit_log(KERN_ALERT, ctx->test, "%pV", vaf); + break; + case LOGLEVEL_CRIT: + kunit_log(KERN_CRIT, ctx->test, "%pV", vaf); + break; + case LOGLEVEL_ERR: + kunit_log(KERN_ERR, ctx->test, "%pV", vaf); + break; + case LOGLEVEL_WARNING: + kunit_log(KERN_WARNING, ctx->test, "%pV", vaf); + break; + case LOGLEVEL_NOTICE: + kunit_log(KERN_NOTICE, ctx->test, "%pV", vaf); + break; + case LOGLEVEL_DEBUG: + kunit_log(KERN_DEBUG, ctx->test, "%pV", vaf); + break; + case LOGLEVEL_INFO: + default: + kunit_log(KERN_INFO, ctx->test, "%pV", vaf); + break; + } +} + +/** + * drm_kunit_helper_printer - Creates a &drm_printer logging into a KUnit test log + * @test: The test context object + * @level: The log level to log the messages at, one of the KERN_* constants + * + * Creates a &struct drm_printer that will log anything printed through + * it, using kunit_log(), both to the kernel log at the @level log + * level and to the log of the KUnit test @test. + * + * This is the KUnit counterpart of the drm_print.h printers like + * drm_info_printer() or drm_err_printer(), and @level should be the + * log level of the printer it replaces. + * + * Returns: + * A pointer to the &drm_printer, or an ERR_PTR() otherwise. + */ +struct drm_printer * +drm_kunit_helper_printer(struct kunit *test, int level) +{ + struct drm_printer_ctx *ctx; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); + + ctx->level = level; + ctx->p.printfn = drm_kunit_printf; + ctx->p.arg = ctx; + ctx->test = test; + + return &ctx->p; +} +EXPORT_SYMBOL_GPL(drm_kunit_helper_printer); + static const struct drm_mode_config_funcs drm_mode_config_funcs = { .atomic_check = drm_atomic_helper_check, diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index e653bc7b1e40..d38614d87678 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -16,6 +16,10 @@ struct drm_device; struct drm_plane_funcs; struct drm_plane_helper_funcs; +struct drm_printer; struct kunit; +struct drm_printer *drm_kunit_helper_printer(struct kunit *test, + int level); + struct device *drm_kunit_helper_alloc_device(struct kunit *test); void drm_kunit_helper_free_device(struct kunit *test, struct device *dev); -- 2.55.0
