* [PATCH nft] tests: shell: drop metainfo from the json dump comparison
@ 2026-09-11 14:59 Avinash Duduskar
0 siblings, 0 replies; only message in thread
From: Avinash Duduskar @ 2026-09-11 14:59 UTC (permalink / raw)
To: netfilter-devel; +Cc: Pablo Neira Ayuso, Phil Sutter
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
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-11 14:59 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-11 14:59 [PATCH nft] tests: shell: drop metainfo from the json dump comparison Avinash Duduskar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox