mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			173 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 804e52d3fe0d75c6ae186b483357ad83b7048495 Mon Sep 17 00:00:00 2001
 | 
						|
From: David Gow <davidgow@google.com>
 | 
						|
Date: Fri, 25 Nov 2022 16:43:05 +0800
 | 
						|
Subject: [PATCH] kunit: Use the static key when retrieving the current test
 | 
						|
 | 
						|
In order to detect if a KUnit test is running, and to access its
 | 
						|
context, the 'kunit_test' member of the current task_struct is used.
 | 
						|
Usually, this is accessed directly or via the kunit_fail_current_task()
 | 
						|
function.
 | 
						|
 | 
						|
In order to speed up the case where no test is running, add a wrapper,
 | 
						|
kunit_get_current_test(), which uses the static key to fail early.
 | 
						|
Equally, Speed up kunit_fail_current_test() by using the static key.
 | 
						|
 | 
						|
This should make it convenient for code to call this
 | 
						|
unconditionally in fakes or error paths, without worrying that this will
 | 
						|
slow the code down significantly.
 | 
						|
 | 
						|
If CONFIG_KUNIT=n (or m), this compiles away to nothing. If
 | 
						|
CONFIG_KUNIT=y, it will compile down to a NOP (on most architectures) if
 | 
						|
no KUnit test is currently running.
 | 
						|
 | 
						|
Note that kunit_get_current_test() does not work if KUnit is built as a
 | 
						|
module. This mirrors the existing restriction on kunit_fail_current_test().
 | 
						|
 | 
						|
Note that the definition of kunit_fail_current_test() still wraps an
 | 
						|
empty, inline function if KUnit is not built-in. This is to ensure that
 | 
						|
the printf format string __attribute__ will still work.
 | 
						|
 | 
						|
Also update the documentation to suggest users use the new
 | 
						|
kunit_get_current_test() function, update the example, and to describe
 | 
						|
the behaviour when KUnit is disabled better.
 | 
						|
 | 
						|
Cc: Jonathan Corbet <corbet@lwn.net>
 | 
						|
Cc: Sadiya Kazi <sadiyakazi@google.com>
 | 
						|
Signed-off-by: David Gow <davidgow@google.com>
 | 
						|
Reviewed-by: Daniel Latypov <dlatypov@google.com>
 | 
						|
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
 | 
						|
---
 | 
						|
 Documentation/dev-tools/kunit/usage.rst | 30 +++++++++-----
 | 
						|
 include/kunit/test-bug.h                | 53 +++++++++++++++++++++++--
 | 
						|
 2 files changed, 71 insertions(+), 12 deletions(-)
 | 
						|
 | 
						|
--- a/Documentation/dev-tools/kunit/usage.rst
 | 
						|
+++ b/Documentation/dev-tools/kunit/usage.rst
 | 
						|
@@ -625,17 +625,23 @@ as shown in next section: *Accessing The
 | 
						|
 Accessing The Current Test
 | 
						|
 --------------------------
 | 
						|
 
 | 
						|
-In some cases, we need to call test-only code from outside the test file.
 | 
						|
-For example, see example in section *Injecting Test-Only Code* or if
 | 
						|
-we are providing a fake implementation of an ops struct. Using
 | 
						|
-``kunit_test`` field in ``task_struct``, we can access it via
 | 
						|
-``current->kunit_test``.
 | 
						|
+In some cases, we need to call test-only code from outside the test file.  This
 | 
						|
+is helpful, for example, when providing a fake implementation of a function, or
 | 
						|
+to fail any current test from within an error handler.
 | 
						|
+We can do this via the ``kunit_test`` field in ``task_struct``, which we can
 | 
						|
+access using the ``kunit_get_current_test()`` function in ``kunit/test-bug.h``.
 | 
						|
+
 | 
						|
+``kunit_get_current_test()`` is safe to call even if KUnit is not enabled. If
 | 
						|
+KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is
 | 
						|
+running in the current task, it will return ``NULL``. This compiles down to
 | 
						|
+either a no-op or a static key check, so will have a negligible performance
 | 
						|
+impact when no test is running.
 | 
						|
 
 | 
						|
-The example below includes how to implement "mocking":
 | 
						|
+The example below uses this to implement a "mock" implementation of a function, ``foo``:
 | 
						|
 
 | 
						|
 .. code-block:: c
 | 
						|
 
 | 
						|
-	#include <linux/sched.h> /* for current */
 | 
						|
+	#include <kunit/test-bug.h> /* for kunit_get_current_test */
 | 
						|
 
 | 
						|
 	struct test_data {
 | 
						|
 		int foo_result;
 | 
						|
@@ -644,7 +650,7 @@ The example below includes how to implem
 | 
						|
 
 | 
						|
 	static int fake_foo(int arg)
 | 
						|
 	{
 | 
						|
-		struct kunit *test = current->kunit_test;
 | 
						|
+		struct kunit *test = kunit_get_current_test();
 | 
						|
 		struct test_data *test_data = test->priv;
 | 
						|
 
 | 
						|
 		KUNIT_EXPECT_EQ(test, test_data->want_foo_called_with, arg);
 | 
						|
@@ -675,7 +681,7 @@ Each test can have multiple resources wh
 | 
						|
 flexibility as a ``priv`` member, but also, for example, allowing helper
 | 
						|
 functions to create resources without conflicting with each other. It is also
 | 
						|
 possible to define a clean up function for each resource, making it easy to
 | 
						|
-avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/test.rst.
 | 
						|
+avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/resource.rst.
 | 
						|
 
 | 
						|
 Failing The Current Test
 | 
						|
 ------------------------
 | 
						|
@@ -703,3 +709,9 @@ structures as shown below:
 | 
						|
 	static void my_debug_function(void) { }
 | 
						|
 	#endif
 | 
						|
 
 | 
						|
+``kunit_fail_current_test()`` is safe to call even if KUnit is not enabled. If
 | 
						|
+KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is
 | 
						|
+running in the current task, it will do nothing. This compiles down to either a
 | 
						|
+no-op or a static key check, so will have a negligible performance impact when
 | 
						|
+no test is running.
 | 
						|
+
 | 
						|
--- a/include/kunit/test-bug.h
 | 
						|
+++ b/include/kunit/test-bug.h
 | 
						|
@@ -9,16 +9,63 @@
 | 
						|
 #ifndef _KUNIT_TEST_BUG_H
 | 
						|
 #define _KUNIT_TEST_BUG_H
 | 
						|
 
 | 
						|
-#define kunit_fail_current_test(fmt, ...) \
 | 
						|
-	__kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
 | 
						|
-
 | 
						|
 #if IS_BUILTIN(CONFIG_KUNIT)
 | 
						|
 
 | 
						|
+#include <linux/jump_label.h> /* For static branch */
 | 
						|
+#include <linux/sched.h>
 | 
						|
+
 | 
						|
+/* Static key if KUnit is running any tests. */
 | 
						|
+DECLARE_STATIC_KEY_FALSE(kunit_running);
 | 
						|
+
 | 
						|
+/**
 | 
						|
+ * kunit_get_current_test() - Return a pointer to the currently running
 | 
						|
+ *			      KUnit test.
 | 
						|
+ *
 | 
						|
+ * If a KUnit test is running in the current task, returns a pointer to its
 | 
						|
+ * associated struct kunit. This pointer can then be passed to any KUnit
 | 
						|
+ * function or assertion. If no test is running (or a test is running in a
 | 
						|
+ * different task), returns NULL.
 | 
						|
+ *
 | 
						|
+ * This function is safe to call even when KUnit is disabled. If CONFIG_KUNIT
 | 
						|
+ * is not enabled, it will compile down to nothing and will return quickly no
 | 
						|
+ * test is running.
 | 
						|
+ */
 | 
						|
+static inline struct kunit *kunit_get_current_test(void)
 | 
						|
+{
 | 
						|
+	if (!static_branch_unlikely(&kunit_running))
 | 
						|
+		return NULL;
 | 
						|
+
 | 
						|
+	return current->kunit_test;
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+/**
 | 
						|
+ * kunit_fail_current_test() - If a KUnit test is running, fail it.
 | 
						|
+ *
 | 
						|
+ * If a KUnit test is running in the current task, mark that test as failed.
 | 
						|
+ *
 | 
						|
+ * This macro will only work if KUnit is built-in (though the tests
 | 
						|
+ * themselves can be modules). Otherwise, it compiles down to nothing.
 | 
						|
+ */
 | 
						|
+#define kunit_fail_current_test(fmt, ...) do {					\
 | 
						|
+		if (static_branch_unlikely(&kunit_running)) {			\
 | 
						|
+			__kunit_fail_current_test(__FILE__, __LINE__,		\
 | 
						|
+						  fmt, ##__VA_ARGS__);		\
 | 
						|
+		}								\
 | 
						|
+	} while (0)
 | 
						|
+
 | 
						|
+
 | 
						|
 extern __printf(3, 4) void __kunit_fail_current_test(const char *file, int line,
 | 
						|
 						    const char *fmt, ...);
 | 
						|
 
 | 
						|
 #else
 | 
						|
 
 | 
						|
+static inline struct kunit *kunit_get_current_test(void) { return NULL; }
 | 
						|
+
 | 
						|
+/* We define this with an empty helper function so format string warnings work */
 | 
						|
+#define kunit_fail_current_test(fmt, ...) \
 | 
						|
+		__kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
 | 
						|
+
 | 
						|
 static inline __printf(3, 4) void __kunit_fail_current_test(const char *file, int line,
 | 
						|
 							    const char *fmt, ...)
 | 
						|
 {
 |