Skip to content

Commit 41daf06

Browse files
committed
Merge tag 'linux_kselftest-kunit-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull KUnit updates from Shuah Khan: - a new feature that adds APIs for managing devices introducing a set of helper functions which allow devices (internally a struct kunit_device) to be created and managed by KUnit. These devices will be automatically unregistered on test exit. These helpers can either use a user-provided struct device_driver, or have one automatically created and managed by KUnit. In both cases, the device lives on a new kunit_bus. - changes to switch drm/tests to use kunit devices - several fixes and enhancements to attribute feature - changes to reorganize deferred action function introducing KUNIT_DEFINE_ACTION_WRAPPER - new feature adds ability to run tests after boot using debugfs - fixes and enhancements to string-stream-test: - parse ERR_PTR in string_stream_destroy() - unchecked dereference in bug fix in debugfs_print_results() - handling errors from alloc_string_stream() - NULL-dereference bug fix in kunit_init_suite() * tag 'linux_kselftest-kunit-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (27 commits) kunit: Fix some comments which were mistakenly kerneldoc kunit: Protect string comparisons against NULL kunit: Add example of kunit_activate_static_stub() with pointer-to-function kunit: Allow passing function pointer to kunit_activate_static_stub() kunit: Fix NULL-dereference in kunit_init_suite() if suite->log is NULL kunit: Reset test->priv after each param iteration kunit: Add example for using test->priv drm/tests: Switch to kunit devices ASoC: topology: Replace fake root_device with kunit_device in tests overflow: Replace fake root_device with kunit_device fortify: test: Use kunit_device kunit: Add APIs for managing devices Documentation: Add debugfs docs with run after boot kunit: add ability to run tests after boot using debugfs kunit: add is_init test attribute kunit: add example suite to test init suites kunit: add KUNIT_INIT_TABLE to init linker section kunit: move KUNIT_TABLE out of INIT_DATA kunit: tool: add test for parsing attributes kunit: tool: fix parsing of test attributes ...
2 parents 5d09f61 + 539e582 commit 41daf06

30 files changed

Lines changed: 978 additions & 146 deletions

Documentation/dev-tools/kunit/api/resource.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,12 @@ state on a per-test basis, register custom cleanup actions, and more.
1111

1212
.. kernel-doc:: include/kunit/resource.h
1313
:internal:
14+
15+
Managed Devices
16+
---------------
17+
18+
Functions for using KUnit-managed struct device and struct device_driver.
19+
Include ``kunit/device.h`` to use these.
20+
21+
.. kernel-doc:: include/kunit/device.h
22+
:internal:

Documentation/dev-tools/kunit/run_manual.rst

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,52 @@ loaded.
4949
5050
The results will appear in TAP format in ``dmesg``.
5151

52+
debugfs
53+
=======
54+
55+
KUnit can be accessed from userspace via the debugfs filesystem (See more
56+
information about debugfs at Documentation/filesystems/debugfs.rst).
57+
58+
If ``CONFIG_KUNIT_DEBUGFS`` is enabled, the KUnit debugfs filesystem is
59+
mounted at /sys/kernel/debug/kunit. You can use this filesystem to perform
60+
the following actions.
61+
62+
Retrieve Test Results
63+
=====================
64+
65+
You can use debugfs to retrieve KUnit test results. The test results are
66+
accessible from the debugfs filesystem in the following read-only file:
67+
68+
.. code-block :: bash
69+
70+
/sys/kernel/debug/kunit/<test_suite>/results
71+
72+
The test results are printed in a KTAP document. Note this document is separate
73+
to the kernel log and thus, may have different test suite numbering.
74+
75+
Run Tests After Kernel Has Booted
76+
=================================
77+
78+
You can use the debugfs filesystem to trigger built-in tests to run after
79+
boot. To run the test suite, you can use the following command to write to
80+
the ``/sys/kernel/debug/kunit/<test_suite>/run`` file:
81+
82+
.. code-block :: bash
83+
84+
echo "any string" > /sys/kernel/debugfs/kunit/<test_suite>/run
85+
86+
As a result, the test suite runs and the results are printed to the kernel
87+
log.
88+
89+
However, this feature is not available with KUnit suites that use init data,
90+
because init data may have been discarded after the kernel boots. KUnit
91+
suites that use init data should be defined using the
92+
kunit_test_init_section_suites() macro.
93+
94+
Also, you cannot use this feature to run tests concurrently. Instead a test
95+
will wait to run until other tests have completed or failed.
96+
5297
.. note ::
5398
54-
If ``CONFIG_KUNIT_DEBUGFS`` is enabled, KUnit test results will
55-
be accessible from the ``debugfs`` filesystem (if mounted).
56-
They will be in ``/sys/kernel/debug/kunit/<test_suite>/results``, in
57-
TAP format.
99+
For test authors, to use this feature, tests will need to correctly initialise
100+
and/or clean up any data, so the test runs correctly a second time.

Documentation/dev-tools/kunit/running_tips.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,3 +428,10 @@ This attribute indicates the name of the module associated with the test.
428428

429429
This attribute is automatically saved as a string and is printed for each suite.
430430
Tests can also be filtered using this attribute.
431+
432+
``is_init``
433+
434+
This attribute indicates whether the test uses init data or functions.
435+
436+
This attribute is automatically saved as a boolean and tests can also be
437+
filtered using this attribute.

Documentation/dev-tools/kunit/usage.rst

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -651,12 +651,16 @@ For example:
651651
}
652652
653653
Note that, for functions like device_unregister which only accept a single
654-
pointer-sized argument, it's possible to directly cast that function to
655-
a ``kunit_action_t`` rather than writing a wrapper function, for example:
654+
pointer-sized argument, it's possible to automatically generate a wrapper
655+
with the ``KUNIT_DEFINE_ACTION_WRAPPER()`` macro, for example:
656656

657657
.. code-block:: C
658658
659-
kunit_add_action(test, (kunit_action_t *)&device_unregister, &dev);
659+
KUNIT_DEFINE_ACTION_WRAPPER(device_unregister, device_unregister_wrapper, struct device *);
660+
kunit_add_action(test, &device_unregister_wrapper, &dev);
661+
662+
You should do this in preference to manually casting to the ``kunit_action_t`` type,
663+
as casting function pointers will break Control Flow Integrity (CFI).
660664

661665
``kunit_add_action`` can fail if, for example, the system is out of memory.
662666
You can use ``kunit_add_action_or_reset`` instead which runs the action
@@ -793,3 +797,53 @@ structures as shown below:
793797
KUnit is not enabled, or if no test is running in the current task, it will do
794798
nothing. This compiles down to either a no-op or a static key check, so will
795799
have a negligible performance impact when no test is running.
800+
801+
Managing Fake Devices and Drivers
802+
---------------------------------
803+
804+
When testing drivers or code which interacts with drivers, many functions will
805+
require a ``struct device`` or ``struct device_driver``. In many cases, setting
806+
up a real device is not required to test any given function, so a fake device
807+
can be used instead.
808+
809+
KUnit provides helper functions to create and manage these fake devices, which
810+
are internally of type ``struct kunit_device``, and are attached to a special
811+
``kunit_bus``. These devices support managed device resources (devres), as
812+
described in Documentation/driver-api/driver-model/devres.rst
813+
814+
To create a KUnit-managed ``struct device_driver``, use ``kunit_driver_create()``,
815+
which will create a driver with the given name, on the ``kunit_bus``. This driver
816+
will automatically be destroyed when the corresponding test finishes, but can also
817+
be manually destroyed with ``driver_unregister()``.
818+
819+
To create a fake device, use the ``kunit_device_register()``, which will create
820+
and register a device, using a new KUnit-managed driver created with ``kunit_driver_create()``.
821+
To provide a specific, non-KUnit-managed driver, use ``kunit_device_register_with_driver()``
822+
instead. Like with managed drivers, KUnit-managed fake devices are automatically
823+
cleaned up when the test finishes, but can be manually cleaned up early with
824+
``kunit_device_unregister()``.
825+
826+
The KUnit devices should be used in preference to ``root_device_register()``, and
827+
instead of ``platform_device_register()`` in cases where the device is not otherwise
828+
a platform device.
829+
830+
For example:
831+
832+
.. code-block:: c
833+
834+
#include <kunit/device.h>
835+
836+
static void test_my_device(struct kunit *test)
837+
{
838+
struct device *fake_device;
839+
const char *dev_managed_string;
840+
841+
// Create a fake device.
842+
fake_device = kunit_device_register(test, "my_device");
843+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fake_device)
844+
845+
// Pass it to functions which need a device.
846+
dev_managed_string = devm_kstrdup(fake_device, "Hello, World!");
847+
848+
// Everything is cleaned up automatically when the test ends.
849+
}

drivers/gpu/drm/tests/drm_kunit_helpers.c

Lines changed: 3 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <drm/drm_kunit_helpers.h>
66
#include <drm/drm_managed.h>
77

8+
#include <kunit/device.h>
89
#include <kunit/resource.h>
910

1011
#include <linux/device.h>
@@ -15,40 +16,6 @@
1516
static const struct drm_mode_config_funcs drm_mode_config_funcs = {
1617
};
1718

18-
static int fake_probe(struct platform_device *pdev)
19-
{
20-
return 0;
21-
}
22-
23-
static struct platform_driver fake_platform_driver = {
24-
.probe = fake_probe,
25-
.driver = {
26-
.name = KUNIT_DEVICE_NAME,
27-
},
28-
};
29-
30-
static void kunit_action_platform_driver_unregister(void *ptr)
31-
{
32-
struct platform_driver *drv = ptr;
33-
34-
platform_driver_unregister(drv);
35-
36-
}
37-
38-
static void kunit_action_platform_device_put(void *ptr)
39-
{
40-
struct platform_device *pdev = ptr;
41-
42-
platform_device_put(pdev);
43-
}
44-
45-
static void kunit_action_platform_device_del(void *ptr)
46-
{
47-
struct platform_device *pdev = ptr;
48-
49-
platform_device_del(pdev);
50-
}
51-
5219
/**
5320
* drm_kunit_helper_alloc_device - Allocate a mock device for a KUnit test
5421
* @test: The test context object
@@ -66,34 +33,7 @@ static void kunit_action_platform_device_del(void *ptr)
6633
*/
6734
struct device *drm_kunit_helper_alloc_device(struct kunit *test)
6835
{
69-
struct platform_device *pdev;
70-
int ret;
71-
72-
ret = platform_driver_register(&fake_platform_driver);
73-
KUNIT_ASSERT_EQ(test, ret, 0);
74-
75-
ret = kunit_add_action_or_reset(test,
76-
kunit_action_platform_driver_unregister,
77-
&fake_platform_driver);
78-
KUNIT_ASSERT_EQ(test, ret, 0);
79-
80-
pdev = platform_device_alloc(KUNIT_DEVICE_NAME, PLATFORM_DEVID_NONE);
81-
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
82-
83-
ret = kunit_add_action_or_reset(test,
84-
kunit_action_platform_device_put,
85-
pdev);
86-
KUNIT_ASSERT_EQ(test, ret, 0);
87-
88-
ret = platform_device_add(pdev);
89-
KUNIT_ASSERT_EQ(test, ret, 0);
90-
91-
ret = kunit_add_action_or_reset(test,
92-
kunit_action_platform_device_del,
93-
pdev);
94-
KUNIT_ASSERT_EQ(test, ret, 0);
95-
96-
return &pdev->dev;
36+
return kunit_device_register(test, KUNIT_DEVICE_NAME);
9737
}
9838
EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_device);
9939

@@ -106,19 +46,7 @@ EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_device);
10646
*/
10747
void drm_kunit_helper_free_device(struct kunit *test, struct device *dev)
10848
{
109-
struct platform_device *pdev = to_platform_device(dev);
110-
111-
kunit_release_action(test,
112-
kunit_action_platform_device_del,
113-
pdev);
114-
115-
kunit_release_action(test,
116-
kunit_action_platform_device_put,
117-
pdev);
118-
119-
kunit_release_action(test,
120-
kunit_action_platform_driver_unregister,
121-
&fake_platform_driver);
49+
kunit_device_unregister(test, dev);
12250
}
12351
EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device);
12452

drivers/gpu/drm/vc4/tests/vc4_mock.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,9 @@ static int __build_mock(struct kunit *test, struct drm_device *drm,
153153
return 0;
154154
}
155155

156-
static void kunit_action_drm_dev_unregister(void *ptr)
157-
{
158-
struct drm_device *drm = ptr;
159-
160-
drm_dev_unregister(drm);
161-
}
156+
KUNIT_DEFINE_ACTION_WRAPPER(kunit_action_drm_dev_unregister,
157+
drm_dev_unregister,
158+
struct drm_device *);
162159

163160
static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5)
164161
{

include/asm-generic/vmlinux.lds.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@
370370
BRANCH_PROFILE() \
371371
TRACE_PRINTKS() \
372372
BPF_RAW_TP() \
373-
TRACEPOINT_STR()
373+
TRACEPOINT_STR() \
374+
KUNIT_TABLE()
374375

375376
/*
376377
* Data section helpers
@@ -700,7 +701,7 @@
700701
EARLYCON_TABLE() \
701702
LSM_TABLE() \
702703
EARLY_LSM_TABLE() \
703-
KUNIT_TABLE()
704+
KUNIT_INIT_TABLE()
704705

705706
#define INIT_TEXT \
706707
*(.init.text .init.text.*) \
@@ -926,6 +927,12 @@
926927
. = ALIGN(8); \
927928
BOUNDED_SECTION_POST_LABEL(.kunit_test_suites, __kunit_suites, _start, _end)
928929

930+
/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */
931+
#define KUNIT_INIT_TABLE() \
932+
. = ALIGN(8); \
933+
BOUNDED_SECTION_POST_LABEL(.kunit_init_test_suites, \
934+
__kunit_init_suites, _start, _end)
935+
929936
#ifdef CONFIG_BLK_DEV_INITRD
930937
#define INIT_RAM_FS \
931938
. = ALIGN(4); \

include/kunit/device.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* KUnit basic device implementation
4+
*
5+
* Helpers for creating and managing fake devices for KUnit tests.
6+
*
7+
* Copyright (C) 2023, Google LLC.
8+
* Author: David Gow <davidgow@google.com>
9+
*/
10+
11+
#ifndef _KUNIT_DEVICE_H
12+
#define _KUNIT_DEVICE_H
13+
14+
#if IS_ENABLED(CONFIG_KUNIT)
15+
16+
#include <kunit/test.h>
17+
18+
struct device;
19+
struct device_driver;
20+
21+
/**
22+
* kunit_driver_create() - Create a struct device_driver attached to the kunit_bus
23+
* @test: The test context object.
24+
* @name: The name to give the created driver.
25+
*
26+
* Creates a struct device_driver attached to the kunit_bus, with the name @name.
27+
* This driver will automatically be cleaned up on test exit.
28+
*
29+
* Return: a stub struct device_driver, managed by KUnit, with the name @name.
30+
*/
31+
struct device_driver *kunit_driver_create(struct kunit *test, const char *name);
32+
33+
/**
34+
* kunit_device_register() - Create a struct device for use in KUnit tests
35+
* @test: The test context object.
36+
* @name: The name to give the created device.
37+
*
38+
* Creates a struct kunit_device (which is a struct device) with the given name,
39+
* and a corresponding driver. The device and driver will be cleaned up on test
40+
* exit, or when kunit_device_unregister is called. See also
41+
* kunit_device_register_with_driver, if you wish to provide your own
42+
* struct device_driver.
43+
*
44+
* Return: a pointer to a struct device which will be cleaned up when the test
45+
* exits, or an error pointer if the device could not be allocated or registered.
46+
*/
47+
struct device *kunit_device_register(struct kunit *test, const char *name);
48+
49+
/**
50+
* kunit_device_register_with_driver() - Create a struct device for use in KUnit tests
51+
* @test: The test context object.
52+
* @name: The name to give the created device.
53+
* @drv: The struct device_driver to associate with the device.
54+
*
55+
* Creates a struct kunit_device (which is a struct device) with the given
56+
* name, and driver. The device will be cleaned up on test exit, or when
57+
* kunit_device_unregister is called. See also kunit_device_register, if you
58+
* wish KUnit to create and manage a driver for you.
59+
*
60+
* Return: a pointer to a struct device which will be cleaned up when the test
61+
* exits, or an error pointer if the device could not be allocated or registered.
62+
*/
63+
struct device *kunit_device_register_with_driver(struct kunit *test,
64+
const char *name,
65+
const struct device_driver *drv);
66+
67+
/**
68+
* kunit_device_unregister() - Unregister a KUnit-managed device
69+
* @test: The test context object which created the device
70+
* @dev: The device.
71+
*
72+
* Unregisters and destroys a struct device which was created with
73+
* kunit_device_register or kunit_device_register_with_driver. If KUnit created
74+
* a driver, cleans it up as well.
75+
*/
76+
void kunit_device_unregister(struct kunit *test, struct device *dev);
77+
78+
#endif
79+
80+
#endif

0 commit comments

Comments
 (0)