Skip to content

Commit 6774e90

Browse files
committed
of: Add test managed wrappers for of_overlay_apply()/of_node_put()
Add test managed wrappers for of_overlay_apply() that automatically removes the overlay when the test is finished. This API is intended for use by KUnit tests that test code which relies on 'struct device_node's and of_*() APIs. KUnit tests will call of_overlay_apply_kunit() to load an overlay that's been built into the kernel image. When the test is complete, the overlay will be removed. This has a few benefits: 1) It keeps the tests hermetic because the overlay is removed when the test is complete. Tests won't even be aware that an overlay was loaded in another test. 2) The overlay code can live right next to the unit test that loads it. The overlay and the unit test can be compiled into one kernel module if desired. 3) We can test different device tree configurations by loading different overlays. The overlays can be written for a specific test, and there can be many of them loaded per-test without needing to jam all possible combinations into one DTB. 4) It also allows KUnit to test device tree dependent code on any architecture, not just UML. This allows KUnit tests to test architecture specific device tree code. There are some potential pitfalls though. Test authors need to be careful to not overwrite properties in the live tree. The easiest way to do this is to add and remove nodes with a 'kunit-' prefix, almost guaranteeing that the same node won't be present in the tree loaded at boot. Suggested-by: Rob Herring <[email protected]> Cc: Rob Herring <[email protected]> Cc: Saravana Kannan <[email protected]> Reviewed-by: Rob Herring (Arm) <[email protected]> Reviewed-by: David Gow <[email protected]> Signed-off-by: Stephen Boyd <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 814cff5 commit 6774e90

File tree

5 files changed

+217
-0
lines changed

5 files changed

+217
-0
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ API Reference
99
test
1010
resource
1111
functionredirection
12+
of
1213

1314

1415
This page documents the KUnit kernel testing API. It is divided into the
1516
following sections:
1617

18+
Core KUnit API
19+
==============
20+
1721
Documentation/dev-tools/kunit/api/test.rst
1822

1923
- Documents all of the standard testing API
@@ -25,3 +29,10 @@ Documentation/dev-tools/kunit/api/resource.rst
2529
Documentation/dev-tools/kunit/api/functionredirection.rst
2630

2731
- Documents the KUnit Function Redirection API
32+
33+
Driver KUnit API
34+
================
35+
36+
Documentation/dev-tools/kunit/api/of.rst
37+
38+
- Documents the KUnit device tree (OF) API
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
====================
4+
Device Tree (OF) API
5+
====================
6+
7+
The KUnit device tree API is used to test device tree (of_*) dependent code.
8+
9+
.. kernel-doc:: include/kunit/of.h
10+
:internal:
11+
12+
.. kernel-doc:: drivers/of/of_kunit_helpers.c
13+
:export:

drivers/of/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ obj-y += kexec.o
1919
endif
2020
endif
2121

22+
obj-$(CONFIG_KUNIT) += of_kunit_helpers.o
2223
obj-$(CONFIG_OF_KUNIT_TEST) += of_test.o
2324

2425
obj-$(CONFIG_OF_UNITTEST) += unittest-data/

drivers/of/of_kunit_helpers.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Test managed DeviceTree APIs
4+
*/
5+
6+
#include <linux/of.h>
7+
#include <linux/of_fdt.h>
8+
9+
#include <kunit/of.h>
10+
#include <kunit/test.h>
11+
#include <kunit/resource.h>
12+
13+
#if defined(CONFIG_OF_OVERLAY) && defined(CONFIG_OF_EARLY_FLATTREE)
14+
15+
static void of_overlay_fdt_apply_kunit_exit(void *ovcs_id)
16+
{
17+
of_overlay_remove(ovcs_id);
18+
}
19+
20+
/**
21+
* of_overlay_fdt_apply_kunit() - Test managed of_overlay_fdt_apply()
22+
* @test: test context
23+
* @overlay_fdt: device tree overlay to apply
24+
* @overlay_fdt_size: size in bytes of @overlay_fdt
25+
* @ovcs_id: identifier of overlay, used to remove the overlay
26+
*
27+
* Just like of_overlay_fdt_apply(), except the overlay is managed by the test
28+
* case and is automatically removed with of_overlay_remove() after the test
29+
* case concludes.
30+
*
31+
* Return: 0 on success, negative errno on failure
32+
*/
33+
int of_overlay_fdt_apply_kunit(struct kunit *test, void *overlay_fdt,
34+
u32 overlay_fdt_size, int *ovcs_id)
35+
{
36+
int ret;
37+
int *copy_id;
38+
39+
copy_id = kunit_kmalloc(test, sizeof(*copy_id), GFP_KERNEL);
40+
if (!copy_id)
41+
return -ENOMEM;
42+
43+
ret = of_overlay_fdt_apply(overlay_fdt, overlay_fdt_size,
44+
ovcs_id, NULL);
45+
if (ret)
46+
return ret;
47+
48+
*copy_id = *ovcs_id;
49+
50+
return kunit_add_action_or_reset(test, of_overlay_fdt_apply_kunit_exit,
51+
copy_id);
52+
}
53+
EXPORT_SYMBOL_GPL(of_overlay_fdt_apply_kunit);
54+
55+
#endif
56+
57+
KUNIT_DEFINE_ACTION_WRAPPER(of_node_put_wrapper, of_node_put, struct device_node *);
58+
59+
/**
60+
* of_node_put_kunit() - Test managed of_node_put()
61+
* @test: test context
62+
* @node: node to pass to `of_node_put()`
63+
*
64+
* Just like of_node_put(), except the node is managed by the test case and is
65+
* automatically put with of_node_put() after the test case concludes.
66+
*/
67+
void of_node_put_kunit(struct kunit *test, struct device_node *node)
68+
{
69+
if (kunit_add_action(test, of_node_put_wrapper, node)) {
70+
KUNIT_FAIL(test,
71+
"Can't allocate a kunit resource to put of_node\n");
72+
}
73+
}
74+
EXPORT_SYMBOL_GPL(of_node_put_kunit);
75+
76+
MODULE_LICENSE("GPL");
77+
MODULE_DESCRIPTION("Test managed DeviceTree APIs");

include/kunit/of.h

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _KUNIT_OF_H
3+
#define _KUNIT_OF_H
4+
5+
#include <kunit/test.h>
6+
7+
struct device_node;
8+
9+
#ifdef CONFIG_OF
10+
11+
void of_node_put_kunit(struct kunit *test, struct device_node *node);
12+
13+
#else
14+
15+
static inline
16+
void of_node_put_kunit(struct kunit *test, struct device_node *node)
17+
{
18+
kunit_skip(test, "requires CONFIG_OF");
19+
}
20+
21+
#endif /* !CONFIG_OF */
22+
23+
#if defined(CONFIG_OF) && defined(CONFIG_OF_OVERLAY) && defined(CONFIG_OF_EARLY_FLATTREE)
24+
25+
int of_overlay_fdt_apply_kunit(struct kunit *test, void *overlay_fdt,
26+
u32 overlay_fdt_size, int *ovcs_id);
27+
#else
28+
29+
static inline int
30+
of_overlay_fdt_apply_kunit(struct kunit *test, void *overlay_fdt,
31+
u32 overlay_fdt_size, int *ovcs_id)
32+
{
33+
kunit_skip(test, "requires CONFIG_OF and CONFIG_OF_OVERLAY and CONFIG_OF_EARLY_FLATTREE for root node");
34+
return -EINVAL;
35+
}
36+
37+
#endif
38+
39+
/**
40+
* __of_overlay_apply_kunit() - Test managed of_overlay_fdt_apply() variant
41+
* @test: test context
42+
* @overlay_begin: start address of overlay to apply
43+
* @overlay_end: end address of overlay to apply
44+
*
45+
* This is mostly internal API. See of_overlay_apply_kunit() for the wrapper
46+
* that makes this easier to use.
47+
*
48+
* Similar to of_overlay_fdt_apply(), except the overlay is managed by the test
49+
* case and is automatically removed with of_overlay_remove() after the test
50+
* case concludes.
51+
*
52+
* Return: 0 on success, negative errno on failure
53+
*/
54+
static inline int __of_overlay_apply_kunit(struct kunit *test,
55+
u8 *overlay_begin,
56+
const u8 *overlay_end)
57+
{
58+
int unused;
59+
60+
return of_overlay_fdt_apply_kunit(test, overlay_begin,
61+
overlay_end - overlay_begin,
62+
&unused);
63+
}
64+
65+
/**
66+
* of_overlay_apply_kunit() - Test managed of_overlay_fdt_apply() for built-in overlays
67+
* @test: test context
68+
* @overlay_name: name of overlay to apply
69+
*
70+
* This macro is used to apply a device tree overlay built with the
71+
* cmd_dt_S_dtbo rule in scripts/Makefile.lib that has been compiled into the
72+
* kernel image or KUnit test module. The overlay is automatically removed when
73+
* the test is finished.
74+
*
75+
* Unit tests that need device tree nodes should compile an overlay file with
76+
* @overlay_name\.dtbo.o in their Makefile along with their unit test and then
77+
* load the overlay during their test. The @overlay_name matches the filename
78+
* of the overlay without the dtbo filename extension. If CONFIG_OF_OVERLAY is
79+
* not enabled, the @test will be skipped.
80+
*
81+
* In the Makefile
82+
*
83+
* .. code-block:: none
84+
*
85+
* obj-$(CONFIG_OF_OVERLAY_KUNIT_TEST) += overlay_test.o kunit_overlay_test.dtbo.o
86+
*
87+
* In the test
88+
*
89+
* .. code-block:: c
90+
*
91+
* static void of_overlay_kunit_of_overlay_apply(struct kunit *test)
92+
* {
93+
* struct device_node *np;
94+
*
95+
* KUNIT_ASSERT_EQ(test, 0,
96+
* of_overlay_apply_kunit(test, kunit_overlay_test));
97+
*
98+
* np = of_find_node_by_name(NULL, "test-kunit");
99+
* KUNIT_EXPECT_NOT_ERR_OR_NULL(test, np);
100+
* of_node_put(np);
101+
* }
102+
*
103+
* Return: 0 on success, negative errno on failure.
104+
*/
105+
#define of_overlay_apply_kunit(test, overlay_name) \
106+
({ \
107+
extern uint8_t __dtbo_##overlay_name##_begin[]; \
108+
extern uint8_t __dtbo_##overlay_name##_end[]; \
109+
\
110+
__of_overlay_apply_kunit((test), \
111+
__dtbo_##overlay_name##_begin, \
112+
__dtbo_##overlay_name##_end); \
113+
})
114+
115+
#endif

0 commit comments

Comments
 (0)