Skip to content

Commit 3b57fb5

Browse files
jacob-kellerkuba-moo
authored andcommitted
tests: kdoc: re-implement in python
The existing kdoc test is written in shell, based on a simple heuristic of checking whether the number of lines of output from scripts/kernel-doc increases. This test can pass in some cases even when new warnings are introduced, such as if a single patch adds some new warnings while removing others. In addition, the provided log output is not very useful to humans. It uses a traditional diff to compare the prior and current warnings. Because the warnings include line number data, this results in an unreadable mess. Implementing a proper comparison in the shell script is possible, but the resulting logic and code is difficult to maintain. Ultimately, what we want to do is a sort of set intersection on the warnings while ignoring line numbers. Implementing this in python is much more practical. As a first step, convert the kdoc test into a python module. Commands are executed via subprocess. The improved comparison algorithm will be implemented in a following change. Since we will be implementing a new comparison algorithm, do not bother porting the "diff" implementation forward. This results in a temporary regression as we no longer compute the difference or file summary for the user. This will be resolved with the following change implementing the improved algorithm. This version has a couple of minor changes worth nothing: 1) The log output is now in stdout instead of stderr, since the python-based tests do not support logging output to the stderr file. 2) We no longer print out "Checking the tree..." lines. 3) The description line is included within the stdout log text as well as the desc file. Signed-off-by: Jacob Keller <[email protected]>
1 parent 1668e7a commit 3b57fb5

File tree

3 files changed

+94
-53
lines changed

3 files changed

+94
-53
lines changed

tests/patch/kdoc/info.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2-
"run": ["kdoc.sh"],
2+
"pymod": "test",
3+
"pyfunc": "kdoc",
34
"pull-requests": true
45
}

tests/patch/kdoc/kdoc.sh

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

tests/patch/kdoc/test.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
3+
""" Test if kernel-doc generates new warnings """
4+
5+
import os
6+
import subprocess
7+
from typing import List, Optional, Tuple
8+
9+
def get_git_head(tree) -> str:
10+
""" Get the git commit ID for head commit. """
11+
12+
cmd = ["git", "rev-parse", "HEAD"]
13+
result = subprocess.run(cmd, cwd=tree.path, capture_output=True, text=True,
14+
check=True)
15+
16+
return result.stdout.strip()
17+
18+
def run_kernel_doc(tree, commitish, files):
19+
""" Run ./scripts/kdoc on a given commit and capture its results. """
20+
21+
cmd = ["git", "checkout", "-q", commitish]
22+
subprocess.run(cmd, cwd=tree.path, capture_output=False, check=True)
23+
24+
cmd = ["./scripts/kernel-doc", "-Wall", "-none"] + files
25+
result = subprocess.run(cmd, cwd=tree.path, text=True, check=False,
26+
stderr=subprocess.PIPE)
27+
28+
return result.stderr.strip().split('\n')
29+
30+
def extract_files(patch):
31+
"""Extract paths added or modified by the patch."""
32+
33+
all_files = set()
34+
mod_files = set()
35+
lines = patch.raw_patch.split("\n")
36+
37+
# Walk lines, skip last since it doesn't have next
38+
for i, line in enumerate(lines[:-1]):
39+
next_line = lines[i + 1]
40+
41+
if not next_line.startswith("+++ b/"):
42+
continue
43+
44+
file_path = next_line[6:]
45+
46+
all_files.add(file_path)
47+
48+
if line != "--- /dev/null":
49+
mod_files.add(file_path)
50+
51+
return list(mod_files), list(all_files)
52+
53+
def kdoc(tree, patch, result_dir) -> Tuple[int, str, str]:
54+
""" Main function / entry point """
55+
56+
mod_files, all_files = extract_files(patch)
57+
58+
if not mod_files or not all_files:
59+
return 1, "Patch has no modified files?", ""
60+
61+
ret = 0
62+
desc = ""
63+
log = []
64+
65+
head_commit = get_git_head(tree)
66+
67+
try:
68+
incumbent_warnings = run_kernel_doc(tree, "HEAD~", mod_files)
69+
log += ["Warnings before patch:"]
70+
log.extend(map(str, incumbent_warnings))
71+
72+
current_warnings = run_kernel_doc(tree, head_commit, all_files)
73+
log += ["", "Current warnings:"]
74+
log.extend(map(str, current_warnings))
75+
except subprocess.CalledProcessError as e:
76+
desc = f'{e.cmd} failed with exit code {e.returncode}'
77+
if e.stderr:
78+
log += e.stderr.split('\n')
79+
ret = 1
80+
81+
return ret, desc, "\n".join(log)
82+
83+
incumbent_count = len(incumbent_warnings)
84+
current_count = len(current_warnings)
85+
86+
desc = f'Errors and warnings before: {incumbent_count} This patch: {current_count}'
87+
log += ["", desc]
88+
89+
if current_count > incumbent_count:
90+
ret = 1
91+
92+
return ret, desc, "\n".join(log)

0 commit comments

Comments
 (0)