diff options
author | Phil Sutter <phil@nwl.cc> | 2025-05-08 17:34:18 +0200 |
---|---|---|
committer | Phil Sutter <phil@nwl.cc> | 2025-05-13 10:48:53 +0200 |
commit | 77c2ecee9bc7025aa6582696f94ee33ee644ecc7 (patch) | |
tree | d44a71674761a2ebe1b69654d0e3791712b48244 | |
parent | a740f2036ad0d50b4a91e110611563809dac420a (diff) |
Ensure these arrays are reduced if containing just a single item and
parser interprets them correctly in any case.
Signed-off-by: Phil Sutter <phil@nwl.cc>
-rwxr-xr-x | tests/shell/testcases/json/single_flag | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/tests/shell/testcases/json/single_flag b/tests/shell/testcases/json/single_flag new file mode 100755 index 00000000..41fab63b --- /dev/null +++ b/tests/shell/testcases/json/single_flag @@ -0,0 +1,189 @@ +#!/bin/bash +# +# Test various "flags" properties in JSON syntax: +# - single item arrays are abbreviated as non-array in output +# - both non-array and single item array accepted in input +# - single and multiple item values are correctly printed in output and +# recognized in input (checked against standard syntax input/output) + +# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json) + +set -e + +json_sanitize() { + sed -e 's/{"metainfo": {[^}]*}}, //' \ + -e 's/\("handle":\) [0-9]*/\1 0/g' +} +back_n_forth() { # (std, json) + $NFT flush ruleset + $NFT -f - <<< "$1" + diff --label "line ${BASH_LINENO[0]}: JSON output" \ + --label "line ${BASH_LINENO[0]}: JSON expect" \ + -u <($NFT -j list ruleset | json_sanitize) <(echo "$2") + + $NFT flush ruleset + $NFT -j -f - <<< "$2" + diff --label "line ${BASH_LINENO[0]}: std output" \ + --label "line ${BASH_LINENO[0]}: std expect" \ + -u <($NFT list ruleset) <(echo "$1") +} +json_equiv() { # (json_in, json_out) + $NFT flush ruleset + $NFT -j -f - <<< "$1" + diff --label "line ${BASH_LINENO[0]}: JSON equiv output" \ + --label "line ${BASH_LINENO[0]}: JSON equiv expect" \ + -u <($NFT -j list ruleset | json_sanitize) <(echo "$2") +} + +# +# test table flags +# + +STD_TABLE_1="table ip t { + flags dormant +}" +JSON_TABLE_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0, "flags": "dormant"}}]}' +JSON_TABLE_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_TABLE_1") + +STD_TABLE_2=$(sed 's/\(flags dormant\)/\1,persist/' <<< "$STD_TABLE_1") +JSON_TABLE_2=$(sed 's/\("flags":\) \("dormant"\)/\1 [\2, "persist"]/' <<< "$JSON_TABLE_1") + +back_n_forth "$STD_TABLE_1" "$JSON_TABLE_1" +json_equiv "$JSON_TABLE_1_EQUIV" "$JSON_TABLE_1" +back_n_forth "$STD_TABLE_2" "$JSON_TABLE_2" + +# +# test set flags +# + +STD_SET_1="table ip t { + set s { + type inet_proto + flags interval + } +}" +JSON_SET_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"set": {"family": "ip", "name": "s", "table": "t", "type": "inet_proto", "handle": 0, "flags": "interval"}}]}' +JSON_SET_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_SET_1") + +STD_SET_2=$(sed 's/\(flags interval\)/\1,timeout/' <<< "$STD_SET_1") +JSON_SET_2=$(sed 's/\("flags":\) \("interval"\)/\1 [\2, "timeout"]/' <<< "$JSON_SET_1") + +back_n_forth "$STD_SET_1" "$JSON_SET_1" +json_equiv "$JSON_SET_1_EQUIV" "$JSON_SET_1" +back_n_forth "$STD_SET_2" "$JSON_SET_2" + +# +# test fib expression flags +# + +STD_FIB_1="table ip t { + chain c { + fib saddr oif exists + } +}" +JSON_FIB_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"match": {"op": "==", "left": {"fib": {"result": "oif", "flags": "saddr"}}, "right": true}}]}}]}' +JSON_FIB_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_FIB_1") + +STD_FIB_2=$(sed 's/\(fib saddr\)/\1 . iif/' <<< "$STD_FIB_1") +JSON_FIB_2=$(sed 's/\("flags":\) \("saddr"\)/\1 [\2, "iif"]/' <<< "$JSON_FIB_1") + +back_n_forth "$STD_FIB_1" "$JSON_FIB_1" +json_equiv "$JSON_FIB_1_EQUIV" "$JSON_FIB_1" +back_n_forth "$STD_FIB_2" "$JSON_FIB_2" + +# +# test nat statement flags +# + +STD_NAT_1="table ip t { + chain c { + dnat to 192.168.0.0/24 persistent + } +}" +JSON_NAT_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"dnat": {"addr": {"prefix": {"addr": "192.168.0.0", "len": 24}}, "flags": "persistent"}}]}}]}' +JSON_NAT_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_NAT_1") + +STD_NAT_2=$(sed 's/\(persistent\)/random,\1/' <<< "$STD_NAT_1") +JSON_NAT_2=$(sed 's/\("flags":\) \("persistent"\)/\1 ["random", \2]/' <<< "$JSON_NAT_1") + +back_n_forth "$STD_NAT_1" "$JSON_NAT_1" +json_equiv "$JSON_NAT_1_EQUIV" "$JSON_NAT_1" +back_n_forth "$STD_NAT_2" "$JSON_NAT_2" + +# +# test log statement flags +# + +STD_LOG_1="table ip t { + chain c { + log flags tcp sequence + } +}" +JSON_LOG_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"log": {"flags": "tcp sequence"}}]}}]}' +JSON_LOG_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_LOG_1") + +STD_LOG_2=$(sed 's/\(tcp sequence\)/\1,options/' <<< "$STD_LOG_1") +JSON_LOG_2=$(sed 's/\("flags":\) \("tcp sequence"\)/\1 [\2, "tcp options"]/' <<< "$JSON_LOG_1") + +back_n_forth "$STD_LOG_1" "$JSON_LOG_1" +json_equiv "$JSON_LOG_1_EQUIV" "$JSON_LOG_1" +back_n_forth "$STD_LOG_2" "$JSON_LOG_2" + +# +# test synproxy statement flags +# + +STD_SYNPROXY_1="table ip t { + chain c { + synproxy sack-perm + } +}" +JSON_SYNPROXY_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"synproxy": {"flags": "sack-perm"}}]}}]}' +JSON_SYNPROXY_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_SYNPROXY_1") + +STD_SYNPROXY_2=$(sed 's/\(sack-perm\)/timestamp \1/' <<< "$STD_SYNPROXY_1") +JSON_SYNPROXY_2=$(sed 's/\("flags":\) \("sack-perm"\)/\1 ["timestamp", \2]/' <<< "$JSON_SYNPROXY_1") + +back_n_forth "$STD_SYNPROXY_1" "$JSON_SYNPROXY_1" +json_equiv "$JSON_SYNPROXY_1_EQUIV" "$JSON_SYNPROXY_1" +back_n_forth "$STD_SYNPROXY_2" "$JSON_SYNPROXY_2" + +# +# test synproxy object flags +# + +STD_SYNPROXY_OBJ_1="table ip t { + synproxy s { + mss 1280 + wscale 64 + sack-perm + } +}" +JSON_SYNPROXY_OBJ_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"synproxy": {"family": "ip", "name": "s", "table": "t", "handle": 0, "mss": 1280, "wscale": 64, "flags": "sack-perm"}}]}' +JSON_SYNPROXY_OBJ_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_SYNPROXY_OBJ_1") + +STD_SYNPROXY_OBJ_2=$(sed 's/ \(sack-perm\)/timestamp \1/' <<< "$STD_SYNPROXY_OBJ_1") +JSON_SYNPROXY_OBJ_2=$(sed 's/\("flags":\) \("sack-perm"\)/\1 ["timestamp", \2]/' <<< "$JSON_SYNPROXY_OBJ_1") + +back_n_forth "$STD_SYNPROXY_OBJ_1" "$JSON_SYNPROXY_OBJ_1" +json_equiv "$JSON_SYNPROXY_OBJ_1_EQUIV" "$JSON_SYNPROXY_OBJ_1" +back_n_forth "$STD_SYNPROXY_OBJ_2" "$JSON_SYNPROXY_OBJ_2" + +# +# test queue statement flags +# + +STD_QUEUE_1="table ip t { + chain c { + queue flags bypass to 1-10 + } +}" +JSON_QUEUE_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"queue": {"num": {"range": [1, 10]}, "flags": "bypass"}}]}}]}' +JSON_QUEUE_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_QUEUE_1") + +STD_QUEUE_2=$(sed 's/\(bypass\)/\1,fanout/' <<< "$STD_QUEUE_1") +JSON_QUEUE_2=$(sed 's/\("flags":\) \("bypass"\)/\1 [\2, "fanout"]/' <<< "$JSON_QUEUE_1") + +back_n_forth "$STD_QUEUE_1" "$JSON_QUEUE_1" +json_equiv "$JSON_QUEUE_1_EQUIV" "$JSON_QUEUE_1" +back_n_forth "$STD_QUEUE_2" "$JSON_QUEUE_2" |