mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 18:03:10 -04:00
Some monitors do not only rely on tracepoint arguments but also on the currently executing task. This makes it more challenging to mock events in KUnit. Define wrapper functions around current, the functionality is mocked only during KUnit, an additional function call is avoided using a static branch unless any (even unrelated) KUnit test is running. Rely on a global mock_current variable that is set only by the RV KUnit tests and cleared on teardown. Unrelated KUnit tests that happen to trigger RV handlers would see it null and use current. Reviewed-by: Nam Cao <namcao@linutronix.de> Reviewed-by: Wen Yang <wen.yang@linux.dev> Link: https://lore.kernel.org/r/20260723074534.43521-14-gmonaco@redhat.com Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
74 lines
2.4 KiB
C
74 lines
2.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (C) 2026-2029 Red Hat, Inc. Gabriele Monaco <gmonaco@redhat.com>
|
|
*
|
|
* Declaration of wrappers to allow mocking core functionality, like current,
|
|
* and other testing utilities.
|
|
* Necessary only when mocking may be needed. If the RV KUnit test is
|
|
* enabled, the wrappers incur an additional function call overhead.
|
|
*/
|
|
|
|
#ifndef _RV_KUNIT_H
|
|
#define _RV_KUNIT_H
|
|
|
|
#if IS_ENABLED(CONFIG_RV_MONITORS_KUNIT_TEST)
|
|
|
|
#include <kunit/test.h>
|
|
#include <kunit/test-bug.h>
|
|
#include <linux/delay.h>
|
|
|
|
int rv_set_testing(struct kunit_suite *suite);
|
|
void rv_clear_testing(struct kunit_suite *suite);
|
|
|
|
#define RV_KUNIT_MAX_MOCK_TASKS 8
|
|
|
|
struct rv_kunit_ctx {
|
|
int reactions, expected;
|
|
int mock_task_count;
|
|
struct task_struct *mock_tasks[RV_KUNIT_MAX_MOCK_TASKS];
|
|
};
|
|
|
|
#define RV_KUNIT_EXPECT_REACTION(test, ctx) \
|
|
do { \
|
|
KUNIT_EXPECT_EQ(test, ctx->reactions, ++ctx->expected); \
|
|
if (ctx->reactions != ctx->expected) \
|
|
ctx->expected = ctx->reactions; \
|
|
} while (0)
|
|
|
|
#define RV_KUNIT_EXPECT_NO_REACTION(test, ctx) \
|
|
do { \
|
|
KUNIT_EXPECT_EQ(test, ctx->reactions, ctx->expected); \
|
|
if (ctx->reactions != ctx->expected) \
|
|
ctx->expected = ctx->reactions; \
|
|
} while (0)
|
|
|
|
#define RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) \
|
|
for (int __done = ({ RV_KUNIT_EXPECT_NO_REACTION(test, ctx); 0; }); \
|
|
!__done; \
|
|
__done = ({ RV_KUNIT_EXPECT_REACTION(test, ctx); 1; }))
|
|
|
|
struct rv_kunit_mon {
|
|
struct rv_monitor *rv_this;
|
|
int (*monitor_init)(void);
|
|
void (*monitor_destroy)(void);
|
|
bool is_per_task;
|
|
int *task_slot;
|
|
void (*task_reset)(struct task_struct *task);
|
|
};
|
|
|
|
void prepare_test(struct kunit *test, const struct rv_kunit_mon *mon);
|
|
void teardown_test(void *arg);
|
|
struct task_struct *rv_kunit_alloc_mock_task(struct kunit *test);
|
|
|
|
void rv_mock_current(struct task_struct *tsk);
|
|
struct task_struct *rv_get_mock_current(void);
|
|
|
|
#define rv_get_current() (unlikely(kunit_get_current_test()) ? rv_get_mock_current() : current)
|
|
|
|
#else /* !CONFIG_RV_MONITORS_KUNIT_TEST */
|
|
|
|
#define rv_get_current() current
|
|
|
|
#endif /* CONFIG_RV_MONITORS_KUNIT_TEST */
|
|
#endif /* _RV_KUNIT_H */
|