bcm27xx: 6.1: add kernel patches
[openwrt/staging/stintel.git] / target / linux / bcm27xx / patches-6.1 / 950-0550-kunit-Use-the-static-key-when-retrieving-the-current.patch
1 From e7950beaf2123170d65709df3988c25a280c05f1 Mon Sep 17 00:00:00 2001
2 From: David Gow <davidgow@google.com>
3 Date: Fri, 25 Nov 2022 16:43:05 +0800
4 Subject: [PATCH] kunit: Use the static key when retrieving the current
5 test
6
7 In order to detect if a KUnit test is running, and to access its
8 context, the 'kunit_test' member of the current task_struct is used.
9 Usually, this is accessed directly or via the kunit_fail_current_task()
10 function.
11
12 In order to speed up the case where no test is running, add a wrapper,
13 kunit_get_current_test(), which uses the static key to fail early.
14 Equally, Speed up kunit_fail_current_test() by using the static key.
15
16 This should make it convenient for code to call this
17 unconditionally in fakes or error paths, without worrying that this will
18 slow the code down significantly.
19
20 If CONFIG_KUNIT=n (or m), this compiles away to nothing. If
21 CONFIG_KUNIT=y, it will compile down to a NOP (on most architectures) if
22 no KUnit test is currently running.
23
24 Note that kunit_get_current_test() does not work if KUnit is built as a
25 module. This mirrors the existing restriction on kunit_fail_current_test().
26
27 Note that the definition of kunit_fail_current_test() still wraps an
28 empty, inline function if KUnit is not built-in. This is to ensure that
29 the printf format string __attribute__ will still work.
30
31 Also update the documentation to suggest users use the new
32 kunit_get_current_test() function, update the example, and to describe
33 the behaviour when KUnit is disabled better.
34
35 Cc: Jonathan Corbet <corbet@lwn.net>
36 Cc: Sadiya Kazi <sadiyakazi@google.com>
37 Signed-off-by: David Gow <davidgow@google.com>
38 Reviewed-by: Daniel Latypov <dlatypov@google.com>
39 Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
40 ---
41 Documentation/dev-tools/kunit/usage.rst | 30 +++++++++-----
42 include/kunit/test-bug.h | 53 +++++++++++++++++++++++--
43 2 files changed, 71 insertions(+), 12 deletions(-)
44
45 --- a/Documentation/dev-tools/kunit/usage.rst
46 +++ b/Documentation/dev-tools/kunit/usage.rst
47 @@ -625,17 +625,23 @@ as shown in next section: *Accessing The
48 Accessing The Current Test
49 --------------------------
50
51 -In some cases, we need to call test-only code from outside the test file.
52 -For example, see example in section *Injecting Test-Only Code* or if
53 -we are providing a fake implementation of an ops struct. Using
54 -``kunit_test`` field in ``task_struct``, we can access it via
55 -``current->kunit_test``.
56 +In some cases, we need to call test-only code from outside the test file. This
57 +is helpful, for example, when providing a fake implementation of a function, or
58 +to fail any current test from within an error handler.
59 +We can do this via the ``kunit_test`` field in ``task_struct``, which we can
60 +access using the ``kunit_get_current_test()`` function in ``kunit/test-bug.h``.
61 +
62 +``kunit_get_current_test()`` is safe to call even if KUnit is not enabled. If
63 +KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is
64 +running in the current task, it will return ``NULL``. This compiles down to
65 +either a no-op or a static key check, so will have a negligible performance
66 +impact when no test is running.
67
68 -The example below includes how to implement "mocking":
69 +The example below uses this to implement a "mock" implementation of a function, ``foo``:
70
71 .. code-block:: c
72
73 - #include <linux/sched.h> /* for current */
74 + #include <kunit/test-bug.h> /* for kunit_get_current_test */
75
76 struct test_data {
77 int foo_result;
78 @@ -644,7 +650,7 @@ The example below includes how to implem
79
80 static int fake_foo(int arg)
81 {
82 - struct kunit *test = current->kunit_test;
83 + struct kunit *test = kunit_get_current_test();
84 struct test_data *test_data = test->priv;
85
86 KUNIT_EXPECT_EQ(test, test_data->want_foo_called_with, arg);
87 @@ -675,7 +681,7 @@ Each test can have multiple resources wh
88 flexibility as a ``priv`` member, but also, for example, allowing helper
89 functions to create resources without conflicting with each other. It is also
90 possible to define a clean up function for each resource, making it easy to
91 -avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/test.rst.
92 +avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/resource.rst.
93
94 Failing The Current Test
95 ------------------------
96 @@ -703,3 +709,9 @@ structures as shown below:
97 static void my_debug_function(void) { }
98 #endif
99
100 +``kunit_fail_current_test()`` is safe to call even if KUnit is not enabled. If
101 +KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is
102 +running in the current task, it will do nothing. This compiles down to either a
103 +no-op or a static key check, so will have a negligible performance impact when
104 +no test is running.
105 +
106 --- a/include/kunit/test-bug.h
107 +++ b/include/kunit/test-bug.h
108 @@ -9,16 +9,63 @@
109 #ifndef _KUNIT_TEST_BUG_H
110 #define _KUNIT_TEST_BUG_H
111
112 -#define kunit_fail_current_test(fmt, ...) \
113 - __kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
114 -
115 #if IS_BUILTIN(CONFIG_KUNIT)
116
117 +#include <linux/jump_label.h> /* For static branch */
118 +#include <linux/sched.h>
119 +
120 +/* Static key if KUnit is running any tests. */
121 +DECLARE_STATIC_KEY_FALSE(kunit_running);
122 +
123 +/**
124 + * kunit_get_current_test() - Return a pointer to the currently running
125 + * KUnit test.
126 + *
127 + * If a KUnit test is running in the current task, returns a pointer to its
128 + * associated struct kunit. This pointer can then be passed to any KUnit
129 + * function or assertion. If no test is running (or a test is running in a
130 + * different task), returns NULL.
131 + *
132 + * This function is safe to call even when KUnit is disabled. If CONFIG_KUNIT
133 + * is not enabled, it will compile down to nothing and will return quickly no
134 + * test is running.
135 + */
136 +static inline struct kunit *kunit_get_current_test(void)
137 +{
138 + if (!static_branch_unlikely(&kunit_running))
139 + return NULL;
140 +
141 + return current->kunit_test;
142 +}
143 +
144 +
145 +/**
146 + * kunit_fail_current_test() - If a KUnit test is running, fail it.
147 + *
148 + * If a KUnit test is running in the current task, mark that test as failed.
149 + *
150 + * This macro will only work if KUnit is built-in (though the tests
151 + * themselves can be modules). Otherwise, it compiles down to nothing.
152 + */
153 +#define kunit_fail_current_test(fmt, ...) do { \
154 + if (static_branch_unlikely(&kunit_running)) { \
155 + __kunit_fail_current_test(__FILE__, __LINE__, \
156 + fmt, ##__VA_ARGS__); \
157 + } \
158 + } while (0)
159 +
160 +
161 extern __printf(3, 4) void __kunit_fail_current_test(const char *file, int line,
162 const char *fmt, ...);
163
164 #else
165
166 +static inline struct kunit *kunit_get_current_test(void) { return NULL; }
167 +
168 +/* We define this with an empty helper function so format string warnings work */
169 +#define kunit_fail_current_test(fmt, ...) \
170 + __kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
171 +
172 static inline __printf(3, 4) void __kunit_fail_current_test(const char *file, int line,
173 const char *fmt, ...)
174 {