Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/include/kunit/static_stub.h
26278 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/*
3
* KUnit function redirection (static stubbing) API.
4
*
5
* Copyright (C) 2022, Google LLC.
6
* Author: David Gow <[email protected]>
7
*/
8
#ifndef _KUNIT_STATIC_STUB_H
9
#define _KUNIT_STATIC_STUB_H
10
11
#if !IS_ENABLED(CONFIG_KUNIT)
12
13
/* If CONFIG_KUNIT is not enabled, these stubs quietly disappear. */
14
#define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) do {} while (0)
15
16
#else
17
18
#include <kunit/test.h>
19
#include <kunit/test-bug.h>
20
21
#include <linux/compiler.h> /* for {un,}likely() */
22
#include <linux/sched.h> /* for task_struct */
23
24
25
/**
26
* KUNIT_STATIC_STUB_REDIRECT() - call a replacement 'static stub' if one exists
27
* @real_fn_name: The name of this function (as an identifier, not a string)
28
* @args: All of the arguments passed to this function
29
*
30
* This is a function prologue which is used to allow calls to the current
31
* function to be redirected by a KUnit test. KUnit tests can call
32
* kunit_activate_static_stub() to pass a replacement function in. The
33
* replacement function will be called by KUNIT_STATIC_STUB_REDIRECT(), which
34
* will then return from the function. If the caller is not in a KUnit context,
35
* the function will continue execution as normal.
36
*
37
* Example:
38
*
39
* .. code-block:: c
40
*
41
* int real_func(int n)
42
* {
43
* KUNIT_STATIC_STUB_REDIRECT(real_func, n);
44
* return 0;
45
* }
46
*
47
* int replacement_func(int n)
48
* {
49
* return 42;
50
* }
51
*
52
* void example_test(struct kunit *test)
53
* {
54
* kunit_activate_static_stub(test, real_func, replacement_func);
55
* KUNIT_EXPECT_EQ(test, real_func(1), 42);
56
* }
57
*
58
*/
59
#define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) \
60
do { \
61
typeof(&real_fn_name) replacement; \
62
struct kunit *current_test = kunit_get_current_test(); \
63
\
64
if (likely(!current_test)) \
65
break; \
66
\
67
replacement = kunit_hooks.get_static_stub_address(current_test, \
68
&real_fn_name); \
69
\
70
if (unlikely(replacement)) \
71
return replacement(args); \
72
} while (0)
73
74
/* Helper function for kunit_activate_static_stub(). The macro does
75
* typechecking, so use it instead.
76
*/
77
void __kunit_activate_static_stub(struct kunit *test,
78
void *real_fn_addr,
79
void *replacement_addr);
80
81
/**
82
* kunit_activate_static_stub() - replace a function using static stubs.
83
* @test: A pointer to the 'struct kunit' test context for the current test.
84
* @real_fn_addr: The address of the function to replace.
85
* @replacement_addr: The address of the function to replace it with.
86
*
87
* When activated, calls to real_fn_addr from within this test (even if called
88
* indirectly) will instead call replacement_addr. The function pointed to by
89
* real_fn_addr must begin with the static stub prologue in
90
* KUNIT_STATIC_STUB_REDIRECT() for this to work. real_fn_addr and
91
* replacement_addr must have the same type.
92
*
93
* The redirection can be disabled again with kunit_deactivate_static_stub().
94
*/
95
#define kunit_activate_static_stub(test, real_fn_addr, replacement_addr) do { \
96
typecheck_fn(typeof(&replacement_addr), real_fn_addr); \
97
__kunit_activate_static_stub(test, real_fn_addr, replacement_addr); \
98
} while (0)
99
100
101
/**
102
* kunit_deactivate_static_stub() - disable a function redirection
103
* @test: A pointer to the 'struct kunit' test context for the current test.
104
* @real_fn_addr: The address of the function to no-longer redirect
105
*
106
* Deactivates a redirection configured with kunit_activate_static_stub(). After
107
* this function returns, calls to real_fn_addr() will execute the original
108
* real_fn, not any previously-configured replacement.
109
*/
110
void kunit_deactivate_static_stub(struct kunit *test, void *real_fn_addr);
111
112
#endif
113
#endif
114
115