From: Avinash Duduskar <avinash.duduskar@gmail.com>
To: netfilter-devel@vger.kernel.org
Cc: Pablo Neira Ayuso <pablo@netfilter.org>, Phil Sutter <phil@nwl.cc>
Subject: [PATCH nft] tests: shell: drop metainfo from the json dump comparison
Date: Fri, 11 Sep 2026 20:29:49 +0530 [thread overview]
Message-ID: <20260911145949.30765-1-avinash.duduskar@gmail.com> (raw)
The comparison reads nothing from the metainfo object, but 431 dumps carry
one, so bumping json_schema_version would mean regenerating all of them.
Add a helper that drops the object and apply it to both sides of the dump
diff. Nothing else changes: json-pretty.sh stays as it is, so what nft
emits, what `nft -j --check` is fed and what DUMPGEN writes are untouched.
Nothing then asserts that nft still emits metainfo, so add a test. It also
pins that the jq and python3 branches agree and that both reject a
malformed ruleset, which a host with jq never exercises.
Link: https://lore.kernel.org/netfilter-devel/amnGEhXHD5175bxC@orbyte.nwl.cc/
Suggested-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Avinash Duduskar <avinash.duduskar@gmail.com>
---
tests/shell/helpers/json-strip-metainfo.sh | 39 +++++++++++
tests/shell/helpers/test-wrapper.sh | 24 ++++++-
tests/shell/testcases/json/0009metainfo_0 | 69 +++++++++++++++++++
.../json/dumps/0009metainfo_0.nodump | 0
4 files changed, 129 insertions(+), 3 deletions(-)
create mode 100755 tests/shell/helpers/json-strip-metainfo.sh
create mode 100755 tests/shell/testcases/json/0009metainfo_0
create mode 100644 tests/shell/testcases/json/dumps/0009metainfo_0.nodump
diff --git a/tests/shell/helpers/json-strip-metainfo.sh b/tests/shell/helpers/json-strip-metainfo.sh
new file mode 100755
index 00000000..0115250d
--- /dev/null
+++ b/tests/shell/helpers/json-strip-metainfo.sh
@@ -0,0 +1,39 @@
+#!/bin/bash -e
+
+exec_strip() {
+ # `jq` and the python3 fallback must produce the same output. Both
+ # reject a non-array "nftables" rather than reshaping it. They are not
+ # equivalent on every malformed input, only on what the test pins, and
+ # only nft's own output reaches this.
+
+ if command -v jq &>/dev/null ; then
+ exec jq '
+ if (.nftables | type) != "array" then
+ error("nftables is not an array")
+ else
+ .nftables |= map(select(has("metainfo") | not))
+ end'
+ fi
+
+ # Fallback to python3.
+ exec python3 -c '
+import json
+import sys
+
+parsed = json.load(sys.stdin)
+if not isinstance(parsed.get("nftables"), list):
+ sys.exit("nftables is not an array")
+parsed["nftables"] = [x for x in parsed["nftables"] if "metainfo" not in x]
+print(json.dumps(parsed, indent=2))
+'
+}
+
+[ "$#" -le 1 ] || { echo "At most one argument supported" ; exit 1 ; }
+
+if [ "$#" -eq 1 ] ; then
+ # One argument passed. This must be a JSON file.
+ [ -f "$1" ] || { echo "File \"$1\" does not exist" ; exit 1 ; }
+ exec_strip < "$1"
+fi
+
+exec_strip
diff --git a/tests/shell/helpers/test-wrapper.sh b/tests/shell/helpers/test-wrapper.sh
index 78a01d56..49b5d66e 100755
--- a/tests/shell/helpers/test-wrapper.sh
+++ b/tests/shell/helpers/test-wrapper.sh
@@ -54,6 +54,12 @@ json_pretty() {
"$NFT_TEST_BASEDIR/helpers/json-pretty.sh" "$@" 2>&1 || :
}
+json_strip_metainfo() {
+ # No `|| :` here. A failure must fail the dump check, not silently
+ # leave a truncated file for the diff to compare.
+ "$NFT_TEST_BASEDIR/helpers/json-strip-metainfo.sh" "$@"
+}
+
TEST="$1"
TESTBASE="$(basename "$TEST")"
TESTDIR="$(dirname "$TEST")"
@@ -228,11 +234,23 @@ if [ "$rc_test" -ne 77 -a "$dump_written" != y ] ; then
diff_check_setcount "$DUMPFILE" "$NFT_TEST_TESTTMPDIR/ruleset-after"
fi
if [ "$NFT_TEST_HAVE_json" != n -a -f "$JDUMPFILE" ] ; then
- if ! $DIFF -u "$JDUMPFILE" "$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty" &> "$NFT_TEST_TESTTMPDIR/ruleset-diff.json" ; then
- show_file "$NFT_TEST_TESTTMPDIR/ruleset-diff.json" "Failed \`$DIFF -u \"$JDUMPFILE\" \"$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty\"\`" >> "$NFT_TEST_TESTTMPDIR/rc-failed-dump"
+ # Drop metainfo from both sides: the comparison ignores it, so
+ # a json_schema_version bump needs no dump regeneration.
+ rc_strip=0
+ json_strip_metainfo "$JDUMPFILE" \
+ > "$NFT_TEST_TESTTMPDIR/dump-expected.json-stripped" \
+ 2> "$NFT_TEST_TESTTMPDIR/strip-err" || rc_strip=1
+ json_strip_metainfo "$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty" \
+ > "$NFT_TEST_TESTTMPDIR/ruleset-after.json-stripped" \
+ 2>> "$NFT_TEST_TESTTMPDIR/strip-err" || rc_strip=1
+ if [ "$rc_strip" -ne 0 ] ; then
+ show_file "$NFT_TEST_TESTTMPDIR/strip-err" "Command \`json-strip-metainfo.sh\` failed" >> "$NFT_TEST_TESTTMPDIR/rc-failed-dump"
+ rc_dump=1
+ elif ! $DIFF -u "$NFT_TEST_TESTTMPDIR/dump-expected.json-stripped" "$NFT_TEST_TESTTMPDIR/ruleset-after.json-stripped" &> "$NFT_TEST_TESTTMPDIR/ruleset-diff.json" ; then
+ show_file "$NFT_TEST_TESTTMPDIR/ruleset-diff.json" "Failed \`$DIFF -u \"$NFT_TEST_TESTTMPDIR/dump-expected.json-stripped\" \"$NFT_TEST_TESTTMPDIR/ruleset-after.json-stripped\"\` (metainfo stripped from \"$JDUMPFILE\" and the live dump)" >> "$NFT_TEST_TESTTMPDIR/rc-failed-dump"
rc_dump=1
else
- rm -f "$NFT_TEST_TESTTMPDIR/ruleset-diff.json"
+ rm -f "$NFT_TEST_TESTTMPDIR/ruleset-diff.json" "$NFT_TEST_TESTTMPDIR/strip-err"
fi
fi
fi
diff --git a/tests/shell/testcases/json/0009metainfo_0 b/tests/shell/testcases/json/0009metainfo_0
new file mode 100755
index 00000000..63b726a0
--- /dev/null
+++ b/tests/shell/testcases/json/0009metainfo_0
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json)
+
+# The dump comparison strips the metainfo object, so nothing else asserts
+# that nft still emits one. Both branches of the strip helper are exercised
+# here too, because a host with jq never runs the python3 fallback. The
+# ruleset below is scaffolding for those checks, hence the .nodump stub.
+
+set -e
+
+STRIP="$NFT_TEST_BASEDIR/helpers/json-strip-metainfo.sh"
+
+TMP="$NFT_TEST_TESTTMPDIR/metainfo"
+mkdir -p "$TMP"
+
+$NFT flush ruleset
+$NFT add table ip t
+$NFT add chain ip t c
+
+$NFT -j list ruleset > "$TMP/ruleset.json"
+
+if ! grep -q '"metainfo"' "$TMP/ruleset.json" ; then
+ echo "E: nft no longer emits a metainfo object" >&2
+ exit 1
+fi
+if ! grep -q '"json_schema_version"' "$TMP/ruleset.json" ; then
+ echo "E: metainfo carries no json_schema_version" >&2
+ exit 1
+fi
+
+"$STRIP" "$TMP/ruleset.json" > "$TMP/stripped.json"
+
+if grep -q '"metainfo"' "$TMP/stripped.json" ; then
+ echo "E: metainfo survived the strip" >&2
+ cat "$TMP/stripped.json" >&2
+ exit 1
+fi
+if ! grep -q '"table"' "$TMP/stripped.json" ; then
+ echo "E: the strip removed more than metainfo" >&2
+ cat "$TMP/stripped.json" >&2
+ exit 1
+fi
+
+# Both branches must agree. Hide jq so the fallback runs.
+if command -v python3 &>/dev/null ; then
+ mkdir -p "$TMP/nojq"
+ ln -s "$(command -v python3)" "$TMP/nojq/python3"
+ PATH="$TMP/nojq" "$STRIP" "$TMP/ruleset.json" > "$TMP/stripped-python3.json"
+ if ! cmp "$TMP/stripped.json" "$TMP/stripped-python3.json" ; then
+ echo "E: jq and python3 branches disagree" >&2
+ diff -u "$TMP/stripped.json" "$TMP/stripped-python3.json" >&2 || :
+ exit 1
+ fi
+fi
+
+# Malformed input must fail, not be silently reshaped.
+for bad in '{"nftables":{"a":1}}' '{"a":1}' ; do
+ if echo "$bad" | "$STRIP" > /dev/null 2>&1 ; then
+ echo "E: strip accepted malformed input: $bad" >&2
+ exit 1
+ fi
+ if command -v python3 &>/dev/null ; then
+ if echo "$bad" | PATH="$TMP/nojq" "$STRIP" > /dev/null 2>&1 ; then
+ echo "E: python3 branch accepted malformed input: $bad" >&2
+ exit 1
+ fi
+ fi
+done
diff --git a/tests/shell/testcases/json/dumps/0009metainfo_0.nodump b/tests/shell/testcases/json/dumps/0009metainfo_0.nodump
new file mode 100644
index 00000000..e69de29b
base-commit: fcef13a358a0755a0bd980910d47989b064a756d
--
2.55.0
reply other threads:[~2026-09-11 14:59 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20260911145949.30765-1-avinash.duduskar@gmail.com \
--to=avinash.duduskar@gmail.com \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
--cc=phil@nwl.cc \
/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.