| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- /* 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
|