Skip to content

Commit 3255493

Browse files
authored
Merge pull request #912 from ojeda/kunit
rust: improvements to KUnit doctests
2 parents e50706a + 5f80e7a commit 3255493

File tree

9 files changed

+141
-164
lines changed

9 files changed

+141
-164
lines changed

rust/Makefile

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ endif
2727

2828
obj-$(CONFIG_RUST) += exports.o
2929

30+
always-$(CONFIG_RUST_KERNEL_KUNIT_TEST) += doctests_kernel_generated.rs
31+
always-$(CONFIG_RUST_KERNEL_KUNIT_TEST) += doctests_kernel_generated_kunit.c
32+
3033
obj-$(CONFIG_RUST_KERNEL_KUNIT_TEST) += doctests_kernel_generated.o
3134
obj-$(CONFIG_RUST_KERNEL_KUNIT_TEST) += doctests_kernel_generated_kunit.o
3235

@@ -164,11 +167,14 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
164167
--extern build_error --extern macros \
165168
--extern bindings \
166169
--no-run --crate-name kernel -Zunstable-options \
167-
--test-builder $(srctree)/scripts/rustdoc_test_builder.py \
170+
--test-builder $(objtree)/scripts/rustdoc_test_builder \
168171
$< $(rustdoc_test_kernel_quiet); \
169-
$(srctree)/scripts/rustdoc_test_gen.py
172+
$(objtree)/scripts/rustdoc_test_gen
170173

171-
%/doctests_kernel_generated.rs %/doctests_kernel_generated_kunit.c: $(src)/kernel/lib.rs $(obj)/kernel.o FORCE
174+
%/doctests_kernel_generated.rs %/doctests_kernel_generated_kunit.c: \
175+
$(src)/kernel/lib.rs $(obj)/kernel.o \
176+
$(objtree)/scripts/rustdoc_test_builder \
177+
$(objtree)/scripts/rustdoc_test_gen FORCE
172178
$(call if_changed,rustdoc_test_kernel)
173179

174180
# We cannot use `-Zpanic-abort-tests` because some tests are dynamic,

rust/kernel/kasync/executor/workqueue.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -177,19 +177,16 @@ struct ExecutorInner {
177177
/// use kernel::spawn_task;
178178
/// use kernel::workqueue;
179179
///
180-
/// fn example_shared_workqueue() -> Result {
181-
/// let mut handle = Executor::try_new(workqueue::system())?;
182-
/// spawn_task!(handle.executor(), async {
183-
/// pr_info!("First workqueue task\n");
184-
/// })?;
185-
/// spawn_task!(handle.executor(), async {
186-
/// pr_info!("Second workqueue task\n");
187-
/// })?;
188-
/// handle.detach();
189-
/// Ok(())
190-
/// }
180+
/// let mut handle = Executor::try_new(workqueue::system())?;
181+
/// spawn_task!(handle.executor(), async {
182+
/// pr_info!("First workqueue task\n");
183+
/// })?;
184+
/// spawn_task!(handle.executor(), async {
185+
/// pr_info!("Second workqueue task\n");
186+
/// })?;
187+
/// handle.detach();
191188
///
192-
/// # example_shared_workqueue().unwrap();
189+
/// # Ok::<(), Error>(())
193190
/// ```
194191
pub struct Executor {
195192
queue: Either<BoxedQueue, &'static Queue>,

rust/kernel/rbtree.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ struct Node<K, V> {
3939
/// ```
4040
/// use kernel::rbtree::RBTree;
4141
///
42-
/// # fn test() -> Result {
4342
/// // Create a new tree.
4443
/// let mut tree = RBTree::new();
4544
///
@@ -110,10 +109,7 @@ struct Node<K, V> {
110109
/// assert!(iter.next().is_none());
111110
/// }
112111
///
113-
/// # Ok(())
114-
/// # }
115-
/// #
116-
/// # assert_eq!(test(), Ok(()));
112+
/// # Ok::<(), Error>(())
117113
/// ```
118114
///
119115
/// In the example below, we first allocate a node, acquire a spinlock, then insert the node into
@@ -140,7 +136,6 @@ struct Node<K, V> {
140136
/// ```
141137
/// use kernel::rbtree::RBTree;
142138
///
143-
/// # fn test() -> Result {
144139
/// // Create a new tree.
145140
/// let mut tree = RBTree::new();
146141
///
@@ -185,10 +180,7 @@ struct Node<K, V> {
185180
/// assert!(iter.next().is_none());
186181
/// }
187182
///
188-
/// # Ok(())
189-
/// # }
190-
/// #
191-
/// # assert_eq!(test(), Ok(()));
183+
/// # Ok::<(), Error>(())
192184
/// ```
193185
pub struct RBTree<K, V> {
194186
root: bindings::rb_root,

rust/kernel/workqueue.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,9 @@ macro_rules! init_work_item_adapter {
119119
///
120120
/// ```
121121
/// # use kernel::{spawn_work_item, workqueue};
122-
///
123-
/// # fn example() -> Result {
124122
/// spawn_work_item!(workqueue::system(), || pr_info!("Hello from a work item\n"))?;
125-
/// # Ok(())
126-
/// # }
127123
///
128-
/// # example().unwrap()
124+
/// # Ok::<(), Error>(())
129125
/// ```
130126
///
131127
/// The following example is used to create a work item and enqueue it several times. We note that
@@ -152,7 +148,6 @@ macro_rules! init_work_item_adapter {
152148
/// }
153149
/// });
154150
///
155-
/// # fn example() -> Result {
156151
/// let e = UniqueArc::try_new(Example {
157152
/// count: AtomicU32::new(0),
158153
/// // SAFETY: `work` is initialised below.
@@ -163,10 +158,8 @@ macro_rules! init_work_item_adapter {
163158
///
164159
/// // Queue the first time.
165160
/// workqueue::system().enqueue(e.into());
166-
/// # Ok(())
167-
/// # }
168161
///
169-
/// # example().unwrap()
162+
/// # Ok::<(), Error>(())
170163
/// ```
171164
///
172165
/// The following example has two different work items in the same struct, which allows it to be
@@ -187,7 +180,6 @@ macro_rules! init_work_item_adapter {
187180
/// struct SecondAdapter;
188181
/// kernel::impl_work_adapter!(SecondAdapter, Example, work2, |_| pr_info!("Second work\n"));
189182
///
190-
/// # fn example() -> Result {
191183
/// let e = UniqueArc::try_new(Example {
192184
/// // SAFETY: `work1` is initialised below.
193185
/// work1: unsafe { Work::new() },
@@ -203,10 +195,8 @@ macro_rules! init_work_item_adapter {
203195
/// // Enqueue the two different work items.
204196
/// workqueue::system().enqueue(e.clone());
205197
/// workqueue::system().enqueue_adapter::<SecondAdapter>(e);
206-
/// # Ok(())
207-
/// # }
208198
///
209-
/// # example().unwrap()
199+
/// # Ok::<(), Error>(())
210200
/// ```
211201
#[repr(transparent)]
212202
pub struct Queue(Opaque<bindings::workqueue_struct>);

scripts/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
/kallsyms
77
/module.lds
88
/recordmcount
9+
/rustdoc_test_builder
10+
/rustdoc_test_gen
911
/sign-file
1012
/sorttable
1113
/unifdef

scripts/Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@ hostprogs-always-$(CONFIG_BUILDTIME_TABLE_SORT) += sorttable
1010
hostprogs-always-$(CONFIG_ASN1) += asn1_compiler
1111
hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
1212
hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
13-
hostprogs-always-$(CONFIG_RUST) += generate_rust_target
13+
hostprogs-always-$(CONFIG_RUST) += \
14+
generate_rust_target \
15+
rustdoc_test_builder \
16+
rustdoc_test_gen
1417

1518
generate_rust_target-rust := y
19+
rustdoc_test_builder-rust := y
20+
rustdoc_test_gen-rust := y
1621

1722
HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
1823
HOSTLDLIBS_sorttable = -lpthread

scripts/rustdoc_test_builder.py

Lines changed: 0 additions & 59 deletions
This file was deleted.

scripts/rustdoc_test_builder.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Test builder for `rustdoc`-generated tests.
4+
5+
use std::fs::File;
6+
use std::io::{BufWriter, Read, Write};
7+
8+
fn main() {
9+
let mut stdin = std::io::stdin().lock();
10+
let mut body = String::new();
11+
stdin.read_to_string(&mut body).unwrap();
12+
13+
let name = body
14+
.lines()
15+
.find_map(|line| {
16+
Some(
17+
line.split_once("fn ")?
18+
.1
19+
.split_once("rust_kernel_")?
20+
.1
21+
.split_once("()")?
22+
.0,
23+
)
24+
.filter(|x| x.chars().all(|c| c.is_alphanumeric() || c == '_'))
25+
})
26+
.expect("No test name found.");
27+
28+
// Qualify `Result` to avoid the collision with our own `Result`
29+
// coming from the prelude.
30+
let body = body.replace(
31+
&format!("rust_kernel_{name}() -> Result<(), impl core::fmt::Debug> {{"),
32+
&format!("rust_kernel_{name}() -> core::result::Result<(), impl core::fmt::Debug> {{"),
33+
);
34+
35+
let name = format!("rust_kernel_doctest_{name}");
36+
let path = format!("rust/test/doctests/kernel/{name}");
37+
38+
write!(
39+
BufWriter::new(File::create(path).unwrap()),
40+
"{name}\n{body}"
41+
)
42+
.unwrap();
43+
}

0 commit comments

Comments
 (0)