Commit 9ba92dc1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'linux-kselftest-kunit-6.5-rc1' of...

Merge tag 'linux-kselftest-kunit-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull KUnit updates from Shuah Khan:

 - kunit_add_action() API to defer a call until test exit

 - Update document to add kunit_add_action() usage notes

 - Changes to always run cleanup from a test kthread

 - Documentation updates to clarify cleanup usage (assertions should not
   be used in cleanup)

 - Documentation update to clearly indicate that exit functions should
   run even if init fails

 - Several fixes and enhancements to existing tests

* tag 'linux-kselftest-kunit-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  MAINTAINERS: Add source tree entry for kunit
  Documentation: kunit: Rename references to kunit_abort()
  kunit: Move kunit_abort() call out of kunit_do_failed_assertion()
  kunit: Fix obsolete name in documentation headers (func->action)
  Documentation: Kunit: add MODULE_LICENSE to sample code
  kunit: Update kunit_print_ok_not_ok function
  kunit: Fix reporting of the skipped parameterized tests
  kunit/test: Add example test showing parameterized testing
  Documentation: kunit: Add usage notes for kunit_add_action()
  kunit: kmalloc_array: Use kunit_add_action()
  kunit: executor_test: Use kunit_add_action()
  kunit: Add kunit_add_action() to defer a call until test exit
  kunit: example: Provide example exit functions
  Documentation: kunit: Warn that exit functions run even if init fails
  Documentation: kunit: Note that assertions should not be used in cleanup
  kunit: Always run cleanup from a test kthread
  Documentation: kunit: Modular tests should not depend on KUNIT=y
  kunit: tool: undo type subscripts for subprocess.Popen
parents b19edac5 2e668335
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -119,9 +119,9 @@ All expectations/assertions are formatted as:
	  terminated immediately.

		- Assertions call the function:
		  ``void __noreturn kunit_abort(struct kunit *)``.
		  ``void __noreturn __kunit_abort(struct kunit *)``.

		- ``kunit_abort`` calls the function:
		- ``__kunit_abort`` calls the function:
		  ``void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)``.

		- ``kunit_try_catch_throw`` calls the function:
+6 −1
Original line number Diff line number Diff line
@@ -250,15 +250,20 @@ Now we are ready to write the test cases.
	};
	kunit_test_suite(misc_example_test_suite);

	MODULE_LICENSE("GPL");

2. Add the following lines to ``drivers/misc/Kconfig``:

.. code-block:: kconfig

	config MISC_EXAMPLE_TEST
		tristate "Test for my example" if !KUNIT_ALL_TESTS
		depends on MISC_EXAMPLE && KUNIT=y
		depends on MISC_EXAMPLE && KUNIT
		default KUNIT_ALL_TESTS

Note: If your test does not support being built as a loadable module (which is
discouraged), replace tristate by bool, and depend on KUNIT=y instead of KUNIT.

3. Add the following lines to ``drivers/misc/Makefile``:

.. code-block:: make
+67 −2
Original line number Diff line number Diff line
@@ -121,6 +121,12 @@ there's an allocation error.
   ``return`` so they only work from the test function. In KUnit, we stop the
   current kthread on failure, so you can call them from anywhere.

.. note::
   Warning: There is an exception to the above rule. You shouldn't use assertions
   in the suite's exit() function, or in the free function for a resource. These
   run when a test is shutting down, and an assertion here prevents further
   cleanup code from running, potentially leading to a memory leak.

Customizing error messages
--------------------------

@@ -160,7 +166,12 @@ many similar tests. In order to reduce duplication in these closely related
tests, most unit testing frameworks (including KUnit) provide the concept of a
*test suite*. A test suite is a collection of test cases for a unit of code
with optional setup and teardown functions that run before/after the whole
suite and/or every test case. For example:
suite and/or every test case.

.. note::
   A test case will only run if it is associated with a test suite.

For example:

.. code-block:: c

@@ -190,7 +201,10 @@ after everything else. ``kunit_test_suite(example_test_suite)`` registers the
test suite with the KUnit test framework.

.. note::
   A test case will only run if it is associated with a test suite.
   The ``exit`` and ``suite_exit`` functions will run even if ``init`` or
   ``suite_init`` fail. Make sure that they can handle any inconsistent
   state which may result from ``init`` or ``suite_init`` encountering errors
   or exiting early.

``kunit_test_suite(...)`` is a macro which tells the linker to put the
specified test suite in a special linker section so that it can be run by KUnit
@@ -601,6 +615,57 @@ For example:
		KUNIT_ASSERT_STREQ(test, buffer, "");
	}

Registering Cleanup Actions
---------------------------

If you need to perform some cleanup beyond simple use of ``kunit_kzalloc``,
you can register a custom "deferred action", which is a cleanup function
run when the test exits (whether cleanly, or via a failed assertion).

Actions are simple functions with no return value, and a single ``void*``
context argument, and fulfill the same role as "cleanup" functions in Python
and Go tests, "defer" statements in languages which support them, and
(in some cases) destructors in RAII languages.

These are very useful for unregistering things from global lists, closing
files or other resources, or freeing resources.

For example:

.. code-block:: C

	static void cleanup_device(void *ctx)
	{
		struct device *dev = (struct device *)ctx;

		device_unregister(dev);
	}

	void example_device_test(struct kunit *test)
	{
		struct my_device dev;

		device_register(&dev);

		kunit_add_action(test, &cleanup_device, &dev);
	}

Note that, for functions like device_unregister which only accept a single
pointer-sized argument, it's possible to directly cast that function to
a ``kunit_action_t`` rather than writing a wrapper function, for example:

.. code-block:: C

	kunit_add_action(test, (kunit_action_t *)&device_unregister, &dev);

``kunit_add_action`` can fail if, for example, the system is out of memory.
You can use ``kunit_add_action_or_reset`` instead which runs the action
immediately if it cannot be deferred.

If you need more control over when the cleanup function is called, you
can trigger it early using ``kunit_release_action``, or cancel it entirely
with ``kunit_remove_action``.


Testing Static Functions
------------------------
+2 −0
Original line number Diff line number Diff line
@@ -11356,6 +11356,8 @@ L: linux-kselftest@vger.kernel.org
L:	kunit-dev@googlegroups.com
S:	Maintained
W:	https://google.github.io/kunit-docs/third_party/kernel/docs/
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git kunit
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git kunit-fixes
F:	Documentation/dev-tools/kunit/
F:	include/kunit/
F:	lib/kunit/
+92 −0
Original line number Diff line number Diff line
@@ -387,4 +387,96 @@ static inline int kunit_destroy_named_resource(struct kunit *test,
 */
void kunit_remove_resource(struct kunit *test, struct kunit_resource *res);

/* A 'deferred action' function to be used with kunit_add_action. */
typedef void (kunit_action_t)(void *);

/**
 * kunit_add_action() - Call a function when the test ends.
 * @test: Test case to associate the action with.
 * @action: The function to run on test exit
 * @ctx: Data passed into @func
 *
 * Defer the execution of a function until the test exits, either normally or
 * due to a failure.  @ctx is passed as additional context. All functions
 * registered with kunit_add_action() will execute in the opposite order to that
 * they were registered in.
 *
 * This is useful for cleaning up allocated memory and resources, as these
 * functions are called even if the test aborts early due to, e.g., a failed
 * assertion.
 *
 * See also: devm_add_action() for the devres equivalent.
 *
 * Returns:
 *   0 on success, an error if the action could not be deferred.
 */
int kunit_add_action(struct kunit *test, kunit_action_t *action, void *ctx);

/**
 * kunit_add_action_or_reset() - Call a function when the test ends.
 * @test: Test case to associate the action with.
 * @action: The function to run on test exit
 * @ctx: Data passed into @func
 *
 * Defer the execution of a function until the test exits, either normally or
 * due to a failure.  @ctx is passed as additional context. All functions
 * registered with kunit_add_action() will execute in the opposite order to that
 * they were registered in.
 *
 * This is useful for cleaning up allocated memory and resources, as these
 * functions are called even if the test aborts early due to, e.g., a failed
 * assertion.
 *
 * If the action cannot be created (e.g., due to the system being out of memory),
 * then action(ctx) will be called immediately, and an error will be returned.
 *
 * See also: devm_add_action_or_reset() for the devres equivalent.
 *
 * Returns:
 *   0 on success, an error if the action could not be deferred.
 */
int kunit_add_action_or_reset(struct kunit *test, kunit_action_t *action,
			      void *ctx);

/**
 * kunit_remove_action() - Cancel a matching deferred action.
 * @test: Test case the action is associated with.
 * @action: The deferred function to cancel.
 * @ctx: The context passed to the deferred function to trigger.
 *
 * Prevent an action deferred via kunit_add_action() from executing when the
 * test terminates.
 *
 * If the function/context pair was deferred multiple times, only the most
 * recent one will be cancelled.
 *
 * See also: devm_remove_action() for the devres equivalent.
 */
void kunit_remove_action(struct kunit *test,
			 kunit_action_t *action,
			 void *ctx);

/**
 * kunit_release_action() - Run a matching action call immediately.
 * @test: Test case the action is associated with.
 * @action: The deferred function to trigger.
 * @ctx: The context passed to the deferred function to trigger.
 *
 * Execute a function deferred via kunit_add_action()) immediately, rather than
 * when the test ends.
 *
 * If the function/context pair was deferred multiple times, it will only be
 * executed once here. The most recent deferral will no longer execute when
 * the test ends.
 *
 * kunit_release_action(test, func, ctx);
 * is equivalent to
 * func(ctx);
 * kunit_remove_action(test, func, ctx);
 *
 * See also: devm_release_action() for the devres equivalent.
 */
void kunit_release_action(struct kunit *test,
			  kunit_action_t *action,
			  void *ctx);
#endif /* _KUNIT_RESOURCE_H */
Loading