mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 10:42:11 +00:00
56bf83de2c
Rust documentation tests are typically examples of usage of any item (e.g. function, struct, module...). They are very convenient because they are just written alongside the documentation, e.g.: /// Sums two numbers. /// /// # Examples /// /// ``` /// assert_eq!(mymod::f(10, 20), 30); /// ``` pub fn f(a: i32, b: i32) -> i32 { a + b } These scripts are used to transform Rust documentation tests into KUnit tests, so that they can be run in-kernel. In turn, this allows us to run tests that use kernel APIs. In particular, the test builder receives `rustdoc`-generated tests, parses them and stores the result. Then, the test generator takes the saved results and generates a KUnit suite where each original documentation test is a test case. For the moment, this is only done for the `kernel` crate, but the plan is to generalize it for other crates and modules. Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com> Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com> Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com> Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
60 lines
1.5 KiB
Python
Executable File
60 lines
1.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
"""rustdoc_test_builder - Test builder for `rustdoc`-generated tests.
|
|
"""
|
|
|
|
import json
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
|
|
RUST_DIR = pathlib.Path("rust")
|
|
TESTS_DIR = RUST_DIR / "test" / "doctests" / "kernel"
|
|
|
|
# `[^\s]*` removes the prefix (e.g. `_doctest_main_`) plus any
|
|
# leading path (for `O=` builds).
|
|
MAIN_RE = re.compile(
|
|
r"^"
|
|
r"fn main\(\) { "
|
|
r"#\[allow\(non_snake_case\)\] "
|
|
r"fn ([^\s]*rust_kernel_([a-zA-Z0-9_]+))\(\) {"
|
|
r"$"
|
|
)
|
|
|
|
def main():
|
|
found_main = False
|
|
test_header = ""
|
|
test_body = ""
|
|
for line in sys.stdin.readlines():
|
|
main_match = MAIN_RE.match(line)
|
|
if main_match:
|
|
if found_main:
|
|
raise Exception("More than one `main` line found.")
|
|
found_main = True
|
|
function_name = main_match.group(1)
|
|
test_name = f"rust_kernel_doctest_{main_match.group(2)}"
|
|
continue
|
|
|
|
if found_main:
|
|
test_body += line
|
|
else:
|
|
test_header += line
|
|
|
|
if not found_main:
|
|
raise Exception("No `main` line found.")
|
|
|
|
call_line = f"}} {function_name}() }}"
|
|
if not test_body.endswith(call_line):
|
|
raise Exception("Unexpected end of test body.")
|
|
test_body = test_body[:-len(call_line)]
|
|
|
|
with open(TESTS_DIR / f"{test_name}.json", "w") as fd:
|
|
json.dump({
|
|
"name": test_name,
|
|
"header": test_header,
|
|
"body": test_body,
|
|
}, fd, sort_keys=True, indent=4)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|