113 lines · 3.6 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0 *//* * KUnit function redirection (static stubbing) API. * * Copyright (C) 2022, Google LLC. * Author: David Gow <davidgow@google.com> */#ifndef _KUNIT_STATIC_STUB_H#define _KUNIT_STATIC_STUB_H #if !IS_ENABLED(CONFIG_KUNIT) /* If CONFIG_KUNIT is not enabled, these stubs quietly disappear. */#define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) do {} while (0) #else #include <kunit/test.h>#include <kunit/test-bug.h> #include <linux/compiler.h> /* for {un,}likely() */#include <linux/sched.h> /* for task_struct */  /** * KUNIT_STATIC_STUB_REDIRECT() - call a replacement 'static stub' if one exists * @real_fn_name: The name of this function (as an identifier, not a string) * @args: All of the arguments passed to this function * * This is a function prologue which is used to allow calls to the current * function to be redirected by a KUnit test. KUnit tests can call * kunit_activate_static_stub() to pass a replacement function in. The * replacement function will be called by KUNIT_STATIC_STUB_REDIRECT(), which * will then return from the function. If the caller is not in a KUnit context, * the function will continue execution as normal. * * Example: * * .. code-block:: c * *	int real_func(int n) *	{ *		KUNIT_STATIC_STUB_REDIRECT(real_func, n); *		return 0; *	} * *	int replacement_func(int n) *	{ *		return 42; *	} * *	void example_test(struct kunit *test) *	{ *		kunit_activate_static_stub(test, real_func, replacement_func); *		KUNIT_EXPECT_EQ(test, real_func(1), 42); *	} * */#define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...)		\do {									\	typeof(&real_fn_name) replacement;				\	struct kunit *current_test = kunit_get_current_test();		\									\	if (likely(!current_test))					\		break;							\									\	replacement = kunit_hooks.get_static_stub_address(current_test,	\							&real_fn_name);	\									\	if (unlikely(replacement))					\		return replacement(args);				\} while (0) /* Helper function for kunit_activate_static_stub(). The macro does * typechecking, so use it instead. */void __kunit_activate_static_stub(struct kunit *test,				  void *real_fn_addr,				  void *replacement_addr); /** * kunit_activate_static_stub() - replace a function using static stubs. * @test: A pointer to the 'struct kunit' test context for the current test. * @real_fn_addr: The address of the function to replace. * @replacement_addr: The address of the function to replace it with. * * When activated, calls to real_fn_addr from within this test (even if called * indirectly) will instead call replacement_addr. The function pointed to by * real_fn_addr must begin with the static stub prologue in * KUNIT_STATIC_STUB_REDIRECT() for this to work. real_fn_addr and * replacement_addr must have the same type. * * The redirection can be disabled again with kunit_deactivate_static_stub(). */#define kunit_activate_static_stub(test, real_fn_addr, replacement_addr) do {	\	typecheck_fn(typeof(&replacement_addr), real_fn_addr);			\	__kunit_activate_static_stub(test, real_fn_addr, replacement_addr);	\} while (0)  /** * kunit_deactivate_static_stub() - disable a function redirection * @test: A pointer to the 'struct kunit' test context for the current test. * @real_fn_addr: The address of the function to no-longer redirect * * Deactivates a redirection configured with kunit_activate_static_stub(). After * this function returns, calls to real_fn_addr() will execute the original * real_fn, not any previously-configured replacement. */void kunit_deactivate_static_stub(struct kunit *test, void *real_fn_addr); #endif#endif