/* SPDX-License-Identifier: GPL-2.0 */1/*2* KUnit function redirection (static stubbing) API.3*4* Copyright (C) 2022, Google LLC.5* Author: David Gow <[email protected]>6*/7#ifndef _KUNIT_STATIC_STUB_H8#define _KUNIT_STATIC_STUB_H910#if !IS_ENABLED(CONFIG_KUNIT)1112/* If CONFIG_KUNIT is not enabled, these stubs quietly disappear. */13#define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) do {} while (0)1415#else1617#include <kunit/test.h>18#include <kunit/test-bug.h>1920#include <linux/compiler.h> /* for {un,}likely() */21#include <linux/sched.h> /* for task_struct */222324/**25* KUNIT_STATIC_STUB_REDIRECT() - call a replacement 'static stub' if one exists26* @real_fn_name: The name of this function (as an identifier, not a string)27* @args: All of the arguments passed to this function28*29* This is a function prologue which is used to allow calls to the current30* function to be redirected by a KUnit test. KUnit tests can call31* kunit_activate_static_stub() to pass a replacement function in. The32* replacement function will be called by KUNIT_STATIC_STUB_REDIRECT(), which33* will then return from the function. If the caller is not in a KUnit context,34* the function will continue execution as normal.35*36* Example:37*38* .. code-block:: c39*40* int real_func(int n)41* {42* KUNIT_STATIC_STUB_REDIRECT(real_func, n);43* return 0;44* }45*46* int replacement_func(int n)47* {48* return 42;49* }50*51* void example_test(struct kunit *test)52* {53* kunit_activate_static_stub(test, real_func, replacement_func);54* KUNIT_EXPECT_EQ(test, real_func(1), 42);55* }56*57*/58#define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) \59do { \60typeof(&real_fn_name) replacement; \61struct kunit *current_test = kunit_get_current_test(); \62\63if (likely(!current_test)) \64break; \65\66replacement = kunit_hooks.get_static_stub_address(current_test, \67&real_fn_name); \68\69if (unlikely(replacement)) \70return replacement(args); \71} while (0)7273/* Helper function for kunit_activate_static_stub(). The macro does74* typechecking, so use it instead.75*/76void __kunit_activate_static_stub(struct kunit *test,77void *real_fn_addr,78void *replacement_addr);7980/**81* kunit_activate_static_stub() - replace a function using static stubs.82* @test: A pointer to the 'struct kunit' test context for the current test.83* @real_fn_addr: The address of the function to replace.84* @replacement_addr: The address of the function to replace it with.85*86* When activated, calls to real_fn_addr from within this test (even if called87* indirectly) will instead call replacement_addr. The function pointed to by88* real_fn_addr must begin with the static stub prologue in89* KUNIT_STATIC_STUB_REDIRECT() for this to work. real_fn_addr and90* replacement_addr must have the same type.91*92* The redirection can be disabled again with kunit_deactivate_static_stub().93*/94#define kunit_activate_static_stub(test, real_fn_addr, replacement_addr) do { \95typecheck_fn(typeof(&replacement_addr), real_fn_addr); \96__kunit_activate_static_stub(test, real_fn_addr, replacement_addr); \97} while (0)9899100/**101* kunit_deactivate_static_stub() - disable a function redirection102* @test: A pointer to the 'struct kunit' test context for the current test.103* @real_fn_addr: The address of the function to no-longer redirect104*105* Deactivates a redirection configured with kunit_activate_static_stub(). After106* this function returns, calls to real_fn_addr() will execute the original107* real_fn, not any previously-configured replacement.108*/109void kunit_deactivate_static_stub(struct kunit *test, void *real_fn_addr);110111#endif112#endif113114115