]>
Commit | Line | Data |
---|---|---|
e047c5ea DG |
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. */ | |
582eb3ae | 14 | #define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) do {} while (0) |
e047c5ea DG |
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 | |
582eb3ae | 33 | * replacement function will be called by KUNIT_STATIC_STUB_REDIRECT(), which |
e047c5ea DG |
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 | |
582eb3ae | 90 | * KUNIT_STATIC_STUB_REDIRECT() for this to work. real_fn_addr and |
e047c5ea DG |
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 { \ | |
fcbac39b | 96 | typecheck_fn(typeof(&replacement_addr), real_fn_addr); \ |
e047c5ea DG |
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 |