From: Hangbin Liu <hangbin.liu@linux.dev>
To: netdev-bot+sashiko@kernel.org
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, horms@kernel.org, shuah@kernel.org,
dsahern@kernel.org, idosch@nvidia.com, andrea.mayer@uniroma2.it,
netdev@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org, liuhangbin@kylinos.cn
Subject: Re: [PATCH net-next v3] selftests: net: move log_test to lib file and remove duplicate code
Date: Thu, 17 Sep 2026 13:54:58 +0800 [thread overview]
Message-ID: <aquAskZZZartTYfH@fedora> (raw)
In-Reply-To: <178961184152.22033.9267194009793243294@kernel.org>
Hi,
Thanks for the review. Since this patch is too long. I will reply the comments
in the summary part.
On Thu, Sep 17, 2026 at 02:24:01AM +0000, netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 5 potential
> issue(s) to consider:
>
> Critical: 0 · High: 1 · Medium: 1 (2) · Low: 3
>
> - [High] SKIP-to-FAIL regression in fib_nexthops.sh, based on a factually
> false claim in the commit message.
In patch v1, sashiko suggested to take the SKIP/XFAIL arms when "expected"
itself is ksft_skip/ksft_xfail? Which would looks like
log_test $rc ksft_xfail.
But ksft_xfail is 2. I'm afraid some test may expect rc=2 and should report
PASS. So I dropped both skip/xfail arms in the function.
Adding a specific handler for fib_nexthops.sh specific seem a little over.
I'd prefer to drop the fib_nexthops.sh change since this is the only
test that covers ksft_xfail in log_test.
> - [Medium] log_test_expected() in lib.sh unconditionally executes
> `ret=$(ksft_exit_status_merge "$ret" "$ksft_fail")` on the failure…
Ack, I will init ret in case some test not using it.
> - [Low] The commit message states "Two callers compared against exit code
> 2 are left as-is since code 2 correctly counts as a failure in the…
sashiko suggested to add a changelog. I will drop the fib_nexthops.sh
changes, so no need to bother.
> - [Low] The migration path advertised in the changelog does not work.
Ack, the fib_nexthops.sh change will be dropped to avoid this.
> - [Low] The changelog justifies a change with a rationale that cannot
> hold: "On failure, ret is set via ksft_exit_status_merge() instead of…
Ack, I will use ret=1 directly.
>
> Pre-existing issues:
> - [Medium] fdb_flush.sh, fib-onlink-tests.sh and l2tp.sh can print [FAIL]
> subtests while exiting with status 0, because they never consume the…
Not update in this patch.
> - [Medium] fib_tests.sh uses the same global `ret` that the shared helper
> treats as cumulative exit status as per-test scratch storage, so a…
Ack, I will add this on my todo list and fix it separately.
Thanks
Hangbin
>
> --
>
> selftests: net: move log_test to lib file and remove duplicate code
>
> This adds a shared log_test_expected() helper to
> tools/testing/selftests/net/lib.sh and replaces the near-identical
> per-script log_test() implementations in 32 net selftests with a thin
> wrapper around it. A few scripts also start sourcing lib.sh instead of
> defining ksft_skip locally.
>
> Link: https://lore.kernel.org/r/20260831-self_log_test-v2-1-eda2e8490cf9@kylinos.cn
> Link: https://lore.kernel.org/r/20260813-self_log_test-v1-1-f88b1107842e@kylinos.cn
>
> A few questions about the conversion below.
>
> > diff --git a/tools/testing/selftests/net/fdb_flush.sh b/tools/testing/selftests/net/fdb_flush.sh
> > index 9931a1e36e3db..4965e52d5ef54 100755
> > --- a/tools/testing/selftests/net/fdb_flush.sh
> > +++ b/tools/testing/selftests/net/fdb_flush.sh
> > @@ -67,40 +67,7 @@ run_cmd()
> >
> > log_test()
> > {
> > - local rc=$1
> > - local expected=$2
> > - local msg="$3"
> > - local nsuccess
> > - local nfail
> > - local ret
> > -
> > - if [ ${rc} -eq ${expected} ]; then
> > - printf "TEST: %-60s [ OK ]\n" "${msg}"
> > - nsuccess=$((nsuccess+1))
> > - else
> > - ret=1
> > - nfail=$((nfail+1))
> > - printf "TEST: %-60s [FAIL]\n" "${msg}"
> > - if [ "$VERBOSE" = "1" ]; then
> > - echo " rc=$rc, expected $expected"
> > - fi
> > -
> > - if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
> > - echo
> > - echo "hit enter to continue, 'q' to quit"
> > - read a
> > - [ "$a" = "q" ] && exit 1
> > - fi
> > - fi
> > -
> > - if [ "${PAUSE}" = "yes" ]; then
> > - echo
> > - echo "hit enter to continue, 'q' to quit"
> > - read a
> > - [ "$a" = "q" ] && exit 1
> > - fi
> > -
> > - [ "$VERBOSE" = "1" ] && echo
> > + log_test_expected "$1" "$2" "$3"
> > }
>
> [Severity: Medium]
> The changelog notes that fdb_flush.sh "used local ret, nsuccess, and nfail,
> which are not used outside the function", but this script has no global ret
> either. A grep for '\bret\b' in fdb_flush.sh, fcnal-test.sh,
> fib-onlink-tests.sh and l2tp.sh at this commit returns no matches.
>
> The failure path of the new helper reads ret unconditionally:
>
> lib.sh:log_test_expected() {
> ...
> ret=$(ksft_exit_status_merge "$ret" "$ksft_fail")
>
> With ret unset, the empty first operand ends up as an associative array
> subscript in the merge helper:
>
> lib.sh:__ksft_status_merge() {
> ...
> if [[ ${weights[$a]} -ge ${weights[$b]} ]]; then
>
> Does bash not print "bad array subscript" here for every failing subtest in
> those four scripts? The merged value still comes out as 1 because the empty
> expansion evaluates as 0, so the visible effect is stderr noise from inside
> lib.sh, one line per failure (fcnal-test.sh has a lot of subtests).
>
> Would it make sense for the shared helper to default the variable, e.g.
> : "${ret:=0}" before the merge, rather than relying on each caller having
> defined it? Also worth noting the copy of this line that previously lived in
> test_bridge_neigh_suppress.sh carried a "# shellcheck disable=SC2154" marker
> for exactly this referenced-but-not-assigned case, and that marker was
> dropped when the code moved into lib.sh.
>
> > diff --git a/tools/testing/selftests/net/fib-onlink-tests.sh b/tools/testing/selftests/net/fib-onlink-tests.sh
> > index e0d45292a2983..a26075abf7d27 100755
> > --- a/tools/testing/selftests/net/fib-onlink-tests.sh
> > +++ b/tools/testing/selftests/net/fib-onlink-tests.sh
> > @@ -85,23 +85,7 @@ PBR_TABLE=101
> >
> > log_test()
> > {
> > - local rc=$1
> > - local expected=$2
> > - local msg="$3"
> > -
> > - if [ ${rc} -eq ${expected} ]; then
> > - nsuccess=$((nsuccess+1))
> > - printf " TEST: %-50s [ OK ]\n" "${msg}"
> > - else
> > - nfail=$((nfail+1))
> > - printf " TEST: %-50s [FAIL]\n" "${msg}"
> > - if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
> > - echo
> > - echo "hit enter to continue, 'q' to quit"
> > - read a
> > - [ "$a" = "q" ] && exit 1
> > - fi
> > - fi
> > + log_test_expected "$1" "$2" "$3"
> > }
>
> [Severity: Medium]
> This isn't a bug introduced by this patch, but it is worth noting while the
> failure bookkeeping is being centralised: fib-onlink-tests.sh, l2tp.sh and
> fdb_flush.sh never consume the status the helper records.
>
> fib-onlink-tests.sh ends with:
>
> if [ "$TESTS" != "none" ]; then
> printf "\nTests passed: %3d\n" ${nsuccess}
> printf "Tests failed: %3d\n" ${nfail}
> fi
>
> l2tp.sh ends with the same two printf lines, and fdb_flush.sh ends with:
>
> for t in $TESTS
> do
> setup; $t; cleanup;
> done
>
> None of the three does exit $ret or derives an exit code from nfail, so can
> these scripts print [FAIL] subtests and still report success to the kselftest
> runner? Since this patch is what makes ret the shared failure accumulator,
> would adding exit $ret to those scripts fit here?
>
> > diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
> > index 431d7bed76224..d0d979e8e438b 100755
> > --- a/tools/testing/selftests/net/fib_nexthops.sh
> > +++ b/tools/testing/selftests/net/fib_nexthops.sh
> > @@ -70,44 +70,7 @@ nsid=100
> >
> > log_test()
> > {
> > - local rc=$1
> > - local expected=$2
> > - local msg="$3"
> > -
> > - if [ ${rc} -eq ${expected} ]; then
> > - printf "TEST: %-60s [ OK ]\n" "${msg}"
> > - nsuccess=$((nsuccess+1))
> > - else
> > - if [[ $rc -eq $ksft_skip ]]; then
> > - [[ $ret -eq 0 ]] && ret=$ksft_skip
> > - nskip=$((nskip+1))
> > - printf "TEST: %-60s [SKIP]\n" "${msg}"
> > - else
> > - ret=1
> > - nfail=$((nfail+1))
> > - printf "TEST: %-60s [FAIL]\n" "${msg}"
> > - fi
>
> [Severity: High]
> The changelog states:
>
> "this test checked for ksft_skip (exit code 4) inside log_test(),
> but no test in the file produces that code."
>
> Are these two call sites not producing exactly that code?
>
> fib_nexthops.sh:ipv6_grp_fcnal() {
> ...
> run_cmd "$IP nexthop add id 103 group 62,1000"
> if [[ $? == 0 ]]; then
> local GRP="id 103 group 62,254/63,255/64,256/65,257/66,65535"
> run_cmd "$IP nexthop replace $GRP"
> check_nexthop "id 103" "$GRP"
> rc=$?
> else
> rc=$ksft_skip
> fi
>
> $IP nexthop flush >/dev/null 2>&1
>
> log_test $rc 0 "16-bit weights"
> }
>
> ipv6_res_grp_fcnal() has the same shape with "group 62,1000 type resilient
> buckets 32".
>
> The else branch is taken whenever iproute2 is too old to accept 16-bit
> nexthop group weights. After this change, log_test_expected() gets rc=4
> against expected 0, so both subtests take the failure branch: [FAIL] is
> printed, nfail is incremented and ret is merged with $ksft_fail.
>
> Combined with exit $ret at the end of the script, does a run on such a host
> change from two [SKIP] lines and exit status 4 to two [FAIL] lines and exit
> status 1?
>
> The changelog suggests "callers that need to report a skip should use
> log_test_skip() instead", but neither of these two callers was converted.
>
> > -
> > - if [ "$VERBOSE" = "1" ]; then
> > - echo " rc=$rc, expected $expected"
> > - fi
> > -
> > - if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
> > - echo
> > - echo "hit enter to continue, 'q' to quit"
> > - read a
> > - [ "$a" = "q" ] && exit 1
> > - fi
> > - fi
> > -
> > - if [ "${PAUSE}" = "yes" ]; then
> > - echo
> > - echo "hit enter to continue, 'q' to quit"
> > - read a
> > - [ "$a" = "q" ] && exit 1
> > - fi
> > -
> > - [ "$VERBOSE" = "1" ] && echo
> > + log_test_expected "$1" "$2" "$3"
> > }
> >
> > run_cmd()
> > @@ -1258,7 +1221,7 @@ ipv6_fcnal_runtime()
> > run_cmd "ip netns exec $me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
> > log_test $? 0 "Ping - group blackhole replaced with gateways"
> > else
> > - log_test 2 0 "Ping - multipath failed"
> > + log_test $rc 0 "Ping - multipath failed"
> > fi
>
> [Severity: Low]
> The changelog says:
>
> "Two callers compared against exit code 2 are left as-is since code 2
> correctly counts as a failure in the previous log_test()."
>
> These are the two callers in question, in ipv6_fcnal_runtime() and
> ipv4_fcnal_runtime(), and they are changed rather than left as-is. Could the
> changelog be updated to describe the substitution?
>
> The change itself looks harmless: run_cmd() assigns rc=$? without declaring
> it local, so under bash dynamic scoping it writes into the caller's local rc,
> and the else branch is only reached when that value is non-zero, so the
> subtest still reports [FAIL] with the same message.
>
> >
> > #
> > @@ -1915,7 +1878,7 @@ ipv4_fcnal_runtime()
> > run_cmd "ip netns exec $me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
> > log_test $? 0 "Ping - group blackhole replaced with gateways"
> > else
> > - log_test 2 0 "Ping - multipath failed"
> > + log_test $rc 0 "Ping - multipath failed"
> > fi
> >
> > #
> > @@ -2729,7 +2692,6 @@ done
> > if [ "$TESTS" != "none" ]; then
> > printf "\nTests passed: %3d\n" ${nsuccess}
> > printf "Tests failed: %3d\n" ${nfail}
> > - printf "Tests skipped: %2d\n" ${nskip}
> > fi
> >
> > exit $ret
>
> [Severity: High]
> With the skip counter line removed and no skip branch left in the shared
> helper, is there any remaining way for this script to report a skipped
> subtest? The two 16-bit weight probes above are the only producers of
> ksft_skip and they are now counted in nfail.
>
> > diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh
> > index b338bfb196a27..7df967a2d6697 100755
> > --- a/tools/testing/selftests/net/fib_tests.sh
> > +++ b/tools/testing/selftests/net/fib_tests.sh
> > @@ -24,31 +24,7 @@ which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
> >
> > log_test()
> > {
> > - local rc=$1
> > - local expected=$2
> > - local msg="$3"
> > -
> > - if [ ${rc} -eq ${expected} ]; then
> > - printf " TEST: %-60s [ OK ]\n" "${msg}"
> > - nsuccess=$((nsuccess+1))
> > - else
> > - ret=1
> > - nfail=$((nfail+1))
> > - printf " TEST: %-60s [FAIL]\n" "${msg}"
>
> [Severity: Medium]
> This is a pre-existing issue, but it interacts with making ret a shared
> cumulative status in lib.sh: fib_tests.sh also uses the same global ret as
> per-test scratch storage.
>
> fib_carrier_unicast_test() starts with an unconditional:
>
> ret=0
>
> and fib6_notify_test()/fib_notify_test() do:
>
> if [ -z "$err" ];then
> ret=0
> else
> ret=1
> fi
>
> log_test $ret 0 "ipv6 route add notify"
>
> None of these declare ret local, and the script finishes with exit $ret. If
> an earlier subtest failed and a later function assigns ret=0 and then passes,
> does the script exit 0 despite the printed [FAIL] lines? Should these
> functions use a local variable now that the helper owns ret?
>
> > - if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
> > - echo
> > - echo "hit enter to continue, 'q' to quit"
> > - read a
> > - [ "$a" = "q" ] && exit 1
> > - fi
> > - fi
> > -
> > - if [ "${PAUSE}" = "yes" ]; then
> > - echo
> > - echo "hit enter to continue, 'q' to quit"
> > - read a
> > - [ "$a" = "q" ] && exit 1
> > - fi
> > + log_test_expected "$1" "$2" "$3"
> > }
> >
> > setup()
>
> [ ... ]
>
> > diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh
> > index d46d2cec89e45..f698fa3d2bd5f 100644
> > --- a/tools/testing/selftests/net/lib.sh
> > +++ b/tools/testing/selftests/net/lib.sh
> > @@ -454,6 +454,39 @@ log_test_xfail()
> > RET=$ksft_xfail retmsg= log_test "$@"
> > }
> >
> > +# Log test result with expected return value
> > +log_test_expected()
> > +{
> > + local rc=$1
> > + local expected=$2
> > + local msg="$3"
> > +
> > + if [ "${rc}" -eq "${expected}" ]; then
> > + nsuccess=$((nsuccess+1))
> > + printf " TEST: %-60s [ OK ]\n" "${msg}"
> > + else
>
> [Severity: Low]
> The changelog points callers at log_test_skip() as the replacement for the
> removed ksft_skip handling. Can that helper work in the converted scripts?
> It dispatches through log_test:
>
> lib.sh:log_test_skip() {
> RET=$ksft_skip retmsg= log_test "$@"
> }
>
> and every script touched here defines its own log_test() after sourcing
> lib.sh:
>
> fib_nexthops.sh:log_test() {
> log_test_expected "$1" "$2" "$3"
> }
>
> so the local definition shadows lib.sh's log_test(). A call like
> log_test_skip "16-bit weights" would then reach log_test_expected with
> rc="16-bit weights", expected="" and msg="", i.e.:
>
> [ "16-bit weights" -eq "" ]
>
> which is an "integer expression expected" error landing in the failure
> branch and printing [FAIL] with an empty test name. There are no callers
> today, so nothing breaks right now, but should the wrapper names be
> reworked so the suggested migration actually works?
>
> > + ret=$(ksft_exit_status_merge "$ret" "$ksft_fail")
>
> [Severity: Low]
> The changelog gives this as the reason for the change:
>
> "On failure, ret is set via ksft_exit_status_merge() instead of ret=1,
> so we can propagate ksft_xfail status correctly."
>
> Is that achievable here? ksft_exit_status_merge() orders the operands as:
>
> lib.sh:ksft_exit_status_merge() {
> ...
> __ksft_status_merge "$a" "$b" \
> $ksft_xfail $ksft_pass $ksft_skip $ksft_fail
> }
>
> so xfail=0, pass=1, skip=2, fail=3, and the operand with the higher weight
> wins. Since $ksft_fail is always passed as the second operand and carries
> the maximum weight, doesn't the result come out as $ksft_fail regardless of
> the previous value of ret, including $ksft_xfail? That makes this line
> equivalent to the old ret=1.
>
> > + nfail=$((nfail+1))
> > + printf " TEST: %-60s [FAIL]\n" "${msg}"
> > + if [ "$VERBOSE" = "1" ]; then
> > + echo " rc=$rc, expected $expected"
> > + fi
> > +
> > + pause_on_fail
> > + fi
> > +
> > + if [ "${PAUSE}" = "yes" ]; then
> > + echo
> > + echo "hit enter to continue, 'q' to quit"
> > + read -r a
> > + [ "$a" = "q" ] && exit 1
> > + fi
> > +
> > + [ "$VERBOSE" = "1" ] && echo
> > +
> > + return 0
> > +}
> > +
> > log_info()
> > {
> > local msg=$1
>
> [ ... ]
>
> --
> Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260915-self_log_test-v3-1-a17728176334%40kylinos.cn
prev parent reply other threads:[~2026-09-17 5:55 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 3:14 [PATCH net-next v3] selftests: net: move log_test to lib file and remove duplicate code Hangbin Liu
2026-09-17 2:24 ` netdev-bot+sashiko
2026-09-17 5:54 ` Hangbin Liu [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aquAskZZZartTYfH@fedora \
--to=hangbin.liu@linux.dev \
--cc=andrea.mayer@uniroma2.it \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=liuhangbin@kylinos.cn \
--cc=netdev-bot+sashiko@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.