From b7d53ebaaeaf1a4e474d6cd85b3b73d557a669a2 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 26 Oct 2025 20:19:57 +0200 Subject: [PATCH] tests: dt_binding_check: new test We currently "rely" on Rob Herring's mail bot to provide sanity checking on patches that touch device tree bindings: https://lore.kernel.org/netdev/176134124286.2841725.8990137232361008022.robh@kernel.org and that is sufficient in "public" settings (patches sent to netdev@vger.kernel.org and devicetree@vger.kernel.org also copied). But in "private" settings (i.e. individual developers encouraged to do sanity checking on their own, for example by running ingest_mdir), we quickly find that Rob's mail bot is apparently closed source, and it has happened more than once (at least to me) for me to miss newly introduced dt_binding_check errors even if I did the due dilligence of running that test locally. So an automated check would be good to have. The justification for including it in NIPA is that while device tree maintainers review binding patches, they get applied to the subsystem tree (in this case netdev). Furthermore, I don't see the overlap with Rob Herring's mail bot as being a strong reason against such checks in NIPA, similar to how the existence of Intel's kbuild test robot does not preclude NIPA from having build tests. In terms of implementation, "make dt_binding_check" does not always nicely print "error" or "warning" on the lines with issues. Furthermore, the errors are multi-line. So instead of filtering for error lines, here we filter out the "normal" lines, which contain things such as "make", "SCHEMA", "CHKDT", "LINT", "DTEX", "DTC" at the beginning. Signed-off-by: Vladimir Oltean --- .../dt_binding_check/dt_binding_check.sh | 86 +++++++++++++++++++ tests/patch/dt_binding_check/info.json | 3 + 2 files changed, 89 insertions(+) create mode 100755 tests/patch/dt_binding_check/dt_binding_check.sh create mode 100644 tests/patch/dt_binding_check/info.json diff --git a/tests/patch/dt_binding_check/dt_binding_check.sh b/tests/patch/dt_binding_check/dt_binding_check.sh new file mode 100755 index 0000000..3c0bf8e --- /dev/null +++ b/tests/patch/dt_binding_check/dt_binding_check.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright 2025 NXP + +HEAD=$(git rev-parse HEAD) +ncpu=$(grep -c processor /proc/cpuinfo) +rc=0 + +pr() { + echo " ====== $* ======" | tee -a /dev/stderr +} + +build() { + make -j $ncpu DT_CHECKER_FLAGS=-m dt_binding_check 2>&1 +} + +# Only run this check if the patch touches DT binding files. +if ! git show --diff-filter=AM --pretty="" --name-only "${HEAD}" | \ + grep -q -E "^Documentation/devicetree/bindings/" +then + echo "No DT binding files touched, skip" >&"$DESC_FD" + exit 0 +fi + +# Create temporary files for logs +tmpfile_o_raw=$(mktemp) +tmpfile_n_raw=$(mktemp) +tmpfile_o_filtered=$(mktemp) +tmpfile_n_filtered=$(mktemp) +tmp_new_issues=$(mktemp) + +echo "Tree base:" +git log -1 --pretty='%h ("%s")' HEAD~ +echo "Now at:" +git log -1 --pretty='%h ("%s")' HEAD + +# Define the filter pattern to exclude build noise from the make output. +# We only want to see the actual error/warning lines. +FILTER_PATTERN="^(make\[| CHKDT| DTC| DTEX| HOSTCC| HOSTLD| LEX| LINT| SCHEMA| YACC|$)" + +pr "Checking before the patch" +git checkout -q HEAD~ + +# Run the check on the parent commit +(build | tee -a "$tmpfile_o_raw") || true + +# Filter and sort the output to get only relevant issue lines +grep -v -E "$FILTER_PATTERN" "$tmpfile_o_raw" | sort > "$tmpfile_o_filtered" +incumbent_total=$(wc -l < "$tmpfile_o_filtered") + +pr "Checking the tree with the patch" +git checkout -q "$HEAD" + +# Run the check on the new commit +(build | tee -a "$tmpfile_n_raw") || true + +# Filter and sort the output +grep -v -E "$FILTER_PATTERN" "$tmpfile_n_raw" | sort > "$tmpfile_n_filtered" +current_total=$(wc -l < "$tmpfile_n_filtered") + +# Compare the filtered lists to find new and fixed issues +# Use comm to find fixed issues (lines only in the old log, column 1). +fixed_issues_count=$(comm -23 "$tmpfile_o_filtered" "$tmpfile_n_filtered" | wc -l) + +# Use comm to find new issues (lines only in the new log, column 2) +# and save them for later display. +comm -13 "$tmpfile_o_filtered" "$tmpfile_n_filtered" > "$tmp_new_issues" +new_issues_count=$(wc -l < "$tmp_new_issues") + +echo "Issues before: $incumbent_total, after: $current_total" \ + "(Fixed: $fixed_issues_count, New: $new_issues_count)" >&"$DESC_FD" + +if [ "$new_issues_count" -gt 0 ]; then + echo "New issues added:" 1>&2 + # Print the new issues we saved + cat "$tmp_new_issues" 1>&2 + rc=1 +elif [ "$fixed_issues_count" -gt 0 ]; then + echo "Patch fixed $fixed_issues_count issue(s)." >&2 + # No new issues, and some were fixed. This is a success. +fi + +rm "$tmpfile_o_raw" "$tmpfile_n_raw" "$tmpfile_o_filtered" "$tmpfile_n_filtered" \ + "$tmp_new_issues" + +exit $rc diff --git a/tests/patch/dt_binding_check/info.json b/tests/patch/dt_binding_check/info.json new file mode 100644 index 0000000..9aaf3aa --- /dev/null +++ b/tests/patch/dt_binding_check/info.json @@ -0,0 +1,3 @@ +{ + "run": ["dt_binding_check.sh"] +}