From: Phil Sutter <phil@nwl.cc>
To: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: netfilter-devel@vger.kernel.org
Subject: [nft PATCH 07/28] tests: py: Implement payload_record()
Date: Thu, 23 Oct 2025 18:13:56 +0200 [thread overview]
Message-ID: <20251023161417.13228-8-phil@nwl.cc> (raw)
In-Reply-To: <20251023161417.13228-1-phil@nwl.cc>
This is a helper function to store payload records (and JSON
equivalents) in .got files. The code it replaces missed to insert a
newline before the new entry and also did not check for existing records
in all spots.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
tests/py/nft-test.py | 117 ++++++++++++++++++++++++++-----------------
1 file changed, 71 insertions(+), 46 deletions(-)
diff --git a/tests/py/nft-test.py b/tests/py/nft-test.py
index 019c828f957a5..dc074d4c3872a 100755
--- a/tests/py/nft-test.py
+++ b/tests/py/nft-test.py
@@ -16,6 +16,7 @@
from __future__ import print_function
import sys
import os
+import io
import argparse
import signal
import json
@@ -741,6 +742,66 @@ def set_delete_elements(set_element, set_name, table, filename=None,
return i > 0
+def payload_record(path, rule, payload, desc="payload"):
+ '''
+ Record payload for @rule in file at @path
+
+ - @payload may be a file handle, a string or an array of strings
+ - Avoid duplicate entries by searching for a match first
+ - Separate entries by a single empty line, so check for trailing newlines
+ before writing
+ - @return False if already existing, True otherwise
+ '''
+ try:
+ with open(path, 'r') as f:
+ lines = f.readlines()
+ except:
+ lines = []
+
+ plines = []
+ if isinstance(payload, io.TextIOWrapper):
+ payload.seek(0, 0)
+ while True:
+ line = payload.readline()
+ if line.startswith("family "):
+ continue
+ if line == "":
+ break
+ plines.append(line)
+ elif isinstance(payload, str):
+ plines = [l + "\n" for l in payload.split("\n")]
+ elif isinstance(payload, list):
+ plines = payload
+ else:
+ raise Exception
+
+ found = False
+ for i in range(len(lines)):
+ if lines[i] == rule + "\n":
+ found = True
+ for pline in plines:
+ i += 1
+ if lines[i] != pline:
+ found = False
+ break
+ if found:
+ return False
+
+ try:
+ with open(path, 'a') as f:
+ if len(lines) > 0 and lines[-1] != "\n":
+ f.write("\n")
+ f.write("# %s\n" % rule)
+ f.writelines(plines)
+ except:
+ warnfmt = "Failed to write %s for rule %s"
+ else:
+ warnfmt = "Wrote %s for rule %s"
+
+ print_warning(warnfmt % (desc, rule[0]), os.path.basename(path), 1)
+ return True
+
+
def json_dump_normalize(json_string, human_readable = False):
json_obj = json.loads(json_string)
@@ -867,28 +928,8 @@ def set_delete_elements(set_element, set_name, table, filename=None,
if state == "ok" and not payload_check(table_payload_expected,
payload_log, cmd):
error += 1
-
- try:
- gotf = open("%s.got" % table_payload_path)
- gotf_payload_expected = payload_find_expected(gotf, rule[0])
- gotf.close()
- except:
- gotf_payload_expected = None
- payload_log.seek(0, 0)
- if not payload_check(gotf_payload_expected, payload_log, cmd):
- gotf = open("%s.got" % table_payload_path, 'a')
- payload_log.seek(0, 0)
- gotf.write("# %s\n" % rule[0])
- while True:
- line = payload_log.readline()
- if line.startswith("family "):
- continue
- if line == "":
- break
- gotf.write(line)
- gotf.close()
- print_warning("Wrote payload for rule %s" % rule[0],
- gotf.name, 1)
+ payload_record("%s.got" % table_payload_path,
+ rule[0], payload_log)
# Check for matching ruleset listing
numeric_proto_old = nftables.set_numeric_proto_output(True)
@@ -979,13 +1020,9 @@ def set_delete_elements(set_element, set_name, table, filename=None,
json_output = item["rule"]
break
json_input = json.dumps(json_output["expr"], sort_keys = True)
-
- gotf = open("%s.json.got" % filename_path, 'a')
- jdump = json_dump_normalize(json_input, True)
- gotf.write("# %s\n%s\n\n" % (rule[0], jdump))
- gotf.close()
- print_warning("Wrote JSON equivalent for rule %s" % rule[0],
- gotf.name, 1)
+ payload_record("%s.json.got" % filename_path, rule[0],
+ json_dump_normalize(json_input, True),
+ "JSON equivalent")
table_flush(table, filename, lineno)
payload_log = tempfile.TemporaryFile(mode="w+")
@@ -1013,17 +1050,8 @@ def set_delete_elements(set_element, set_name, table, filename=None,
# Check for matching payload
if not payload_check(table_payload_expected, payload_log, cmd):
error += 1
- gotf = open("%s.json.payload.got" % filename_path, 'a')
- payload_log.seek(0, 0)
- gotf.write("# %s\n" % rule[0])
- while True:
- line = payload_log.readline()
- if line == "":
- break
- gotf.write(line)
- gotf.close()
- print_warning("Wrote JSON payload for rule %s" % rule[0],
- gotf.name, 1)
+ payload_record("%s.json.payload.got" % filename_path,
+ rule[0], payload_log, "JSON payload")
# Check for matching ruleset listing
numeric_proto_old = nftables.set_numeric_proto_output(True)
@@ -1049,12 +1077,9 @@ def set_delete_elements(set_element, set_name, table, filename=None,
print_differences_warning(filename, lineno,
json_input, json_output, cmd)
error += 1
- gotf = open("%s.json.output.got" % filename_path, 'a')
- jdump = json_dump_normalize(json_output, True)
- gotf.write("# %s\n%s\n\n" % (rule[0], jdump))
- gotf.close()
- print_warning("Wrote JSON output for rule %s" % rule[0],
- gotf.name, 1)
+ payload_record("%s.json.output.got" % filename_path, rule[0],
+ json_dump_normalize(json_output, True),
+ "JSON output")
# prevent further warnings and .got file updates
json_expected = json_output
elif json_expected and json_output != json_expected:
--
2.51.0
next prev parent reply other threads:[~2025-10-23 16:14 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-23 16:13 [nft PATCH 00/28] Fix netlink debug output on Big Endian Phil Sutter
2025-10-23 16:13 ` [nft PATCH 01/28] datatype: Fix boolean type " Phil Sutter
2025-10-23 16:13 ` [nft PATCH 02/28] optimize: Fix verdict expression comparison Phil Sutter
2025-10-23 16:13 ` [nft PATCH 03/28] tests: py: any/tcpopt.t.json: Fix JSON equivalent Phil Sutter
2025-10-23 16:13 ` [nft PATCH 04/28] tests: py: any/ct.t.json.output: Drop leftover entry Phil Sutter
2025-10-23 16:13 ` [nft PATCH 05/28] tests: py: inet/osf.t: Fix element ordering in JSON equivalents Phil Sutter
2025-10-23 16:13 ` [nft PATCH 06/28] tests: py: Fix for using wrong payload path Phil Sutter
2025-10-23 16:13 ` Phil Sutter [this message]
2025-10-23 16:13 ` [nft PATCH 08/28] tests: py: Do not rely upon '[end]' marker Phil Sutter
2025-10-23 16:13 ` [nft PATCH 09/28] netlink: No need to reference array when passing as pointer Phil Sutter
2025-10-23 16:13 ` [nft PATCH 10/28] datatype: Increase symbolic constant printer robustness Phil Sutter
2025-10-29 18:36 ` Pablo Neira Ayuso
2025-10-30 11:00 ` Phil Sutter
2025-10-30 21:56 ` Pablo Neira Ayuso
2025-10-30 22:35 ` Phil Sutter
2025-10-30 23:22 ` Pablo Neira Ayuso
2025-10-23 16:14 ` [nft PATCH 11/28] tests: py: ip6/vmap.t: Drop double whitespace in rule Phil Sutter
2025-10-23 16:14 ` [nft PATCH 12/28] netlink: Zero nft_data_linearize objects when populating Phil Sutter
2025-10-29 18:37 ` Pablo Neira Ayuso
2025-10-30 11:08 ` Phil Sutter
2025-10-30 22:02 ` Pablo Neira Ayuso
2025-10-30 22:54 ` Phil Sutter
2025-10-23 16:14 ` [nft PATCH 13/28] Define string-based data types as Big Endian Phil Sutter
2025-10-29 18:22 ` Pablo Neira Ayuso
2025-10-30 10:20 ` Phil Sutter
2025-10-23 16:14 ` [nft PATCH 14/28] segtree: No byteorder conversion for string prefix len calculation Phil Sutter
2025-10-23 16:14 ` [nft PATCH 15/28] Fix byteorder conversion of concatenated value expressions and ranges Phil Sutter
2025-10-23 16:14 ` [nft PATCH 16/28] expression: Set range expression 'len' field Phil Sutter
2025-10-23 16:14 ` [nft PATCH 17/28] segtree: Export complete data before editing Phil Sutter
2025-10-23 16:14 ` [nft PATCH 18/28] segtree: Drop problematic constant expr len adjustment Phil Sutter
2025-10-23 16:14 ` [nft PATCH 19/28] netlink: Introduce struct nft_data_linearize::byteorder Phil Sutter
2025-10-23 16:14 ` [nft PATCH 20/28] netlink: Introduce struct nft_data_linearize::sizes Phil Sutter
2025-10-29 18:34 ` Pablo Neira Ayuso
2025-10-30 10:53 ` Phil Sutter
2025-10-23 16:14 ` [nft PATCH 21/28] netlink: Make use of nftnl_{expr,set_elem}_set_imm() Phil Sutter
2025-10-23 16:14 ` [nft PATCH 22/28] mergesort: Linearize concatentations in network byte order Phil Sutter
2025-10-29 18:27 ` Pablo Neira Ayuso
2025-10-30 10:47 ` Phil Sutter
2025-10-23 16:14 ` [nft PATCH 23/28] tests: Adjust JSON records to improved element sorting Phil Sutter
2025-10-23 16:14 ` [nft PATCH 24/28] tests: py: tools: Add regen_payloads.sh Phil Sutter
2025-10-23 16:14 ` [nft PATCH 25/28] tests: py: Update payload records Phil Sutter
2025-10-23 16:14 ` [nft PATCH 26/28] utils: Introduce expr_print_debug() Phil Sutter
2025-10-29 12:46 ` Florian Westphal
2025-10-29 18:31 ` Pablo Neira Ayuso
2025-10-30 10:16 ` Phil Sutter
2025-10-23 16:14 ` [nft PATCH 27/28] utils: Cover for missing newline after BUG() messages Phil Sutter
2025-10-29 12:47 ` Florian Westphal
2025-10-30 10:17 ` Phil Sutter
2025-10-23 16:14 ` [nft PATCH 28/28] Drop no longer needed newline in " Phil Sutter
2025-10-29 18:33 ` Pablo Neira Ayuso
2025-10-30 10:51 ` Phil Sutter
2025-10-23 20:45 ` [nft PATCH 00/28] Fix netlink debug output on Big Endian Florian Westphal
2025-10-23 20:47 ` Phil Sutter
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=20251023161417.13228-8-phil@nwl.cc \
--to=phil@nwl.cc \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).